日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

bind函数详解

發布時間:2025/3/15 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bind函数详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

看看man手冊:

BIND(2) Linux Programmer's Manual BIND(2)NAMEbind - bind a name to a socketSYNOPSIS#include <sys/types.h> /* See NOTES */#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);DESCRIPTIONWhen a socket is created with socket(2), it exists in a name space(address family) but has no address assigned to it. bind() assigns theaddress specified by addr to the socket referred to by the filedescriptor sockfd. addrlen specifies the size, in bytes, of theaddress structure pointed to by addr. Traditionally, this operation iscalled “assigning a name to a socket”.It is normally necessary to assign a local address using bind() beforea SOCK_STREAM socket may receive connections (see accept(2)).The rules used in name binding vary between address families. Consultthe manual entries in Section 7 for detailed information. For AF_INETsee ip(7), for AF_INET6 see ipv6(7), for AF_UNIX see unix(7), forAF_APPLETALK see ddp(7), for AF_PACKET see packet(7), for AF_X25 seex25(7) and for AF_NETLINK see netlink(7).The actual structure passed for the addr argument will depend on theaddress family. The sockaddr structure is defined as something like:struct sockaddr {sa_family_t sa_family;char sa_data[14];}The only purpose of this structure is to cast the structure pointerpassed in addr in order to avoid compiler warnings. See EXAMPLE below.RETURN VALUEOn success, zero is returned. On error, -1 is returned, and errno isset appropriately.ERRORSEACCES The address is protected, and the user is not the superuser.EADDRINUSEThe given address is already in use.EADDRINUSE(Internet domain sockets) The port number was specified as zeroin the socket address structure, but, upon attempting to bind toan ephemeral port, it was determined that all port numbers inthe ephemeral port range are currently in use. See the discus‐sion of /proc/sys/net/ipv4/ip_local_port_range ip(7).EBADF sockfd is not a valid descriptor.EINVAL The socket is already bound to an address.EINVAL addrlen is wrong, or addr is not a valid address for thissocket's domain.ENOTSOCKThe file descriptor sockfd does not refer to a socket.The following errors are specific to UNIX domain (AF_UNIX) sockets:EACCES Search permission is denied on a component of the path prefix.(See also path_resolution(7).)EADDRNOTAVAILA nonexistent interface was requested or the requested addresswas not local.EFAULT addr points outside the user's accessible address space.ELOOP Too many symbolic links were encountered in resolving addr.ENAMETOOLONGaddr is too long.ENOENT The file does not exist.ENOMEM Insufficient kernel memory was available.ENOTDIRA component of the path prefix is not a directory.EROFS The socket inode would reside on a read-only filesystem.CONFORMING TOPOSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD (bind() first appeared in4.2BSD).NOTESPOSIX.1 does not require the inclusion of <sys/types.h>, and thisheader file is not required on Linux. However, some historical (BSD)implementations required this header file, and portable applicationsare probably wise to include it.The third argument of bind() is in reality an int (and this is what 4.xBSD and libc4 and libc5 have). Some POSIX confusion resulted in thepresent socklen_t, also used by glibc. See also accept(2).BUGSThe transparent proxy options are not described.EXAMPLEAn example of the use of bind() with Internet domain sockets can befound in getaddrinfo(3).The following example shows how to bind a stream socket in the UNIX(AF_UNIX) domain, and accept connections:#include <sys/socket.h>#include <sys/un.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#define MY_SOCK_PATH "/somepath"#define LISTEN_BACKLOG 50#define handle_error(msg) \do { perror(msg); exit(EXIT_FAILURE); } while (0)intmain(int argc, char *argv[]){int sfd, cfd;struct sockaddr_un my_addr, peer_addr;socklen_t peer_addr_size;sfd = socket(AF_UNIX, SOCK_STREAM, 0);if (sfd == -1)handle_error("socket");memset(&my_addr, 0, sizeof(struct sockaddr_un));/* Clear structure */my_addr.sun_family = AF_UNIX;strncpy(my_addr.sun_path, MY_SOCK_PATH,sizeof(my_addr.sun_path) - 1);if (bind(sfd, (struct sockaddr *) &my_addr,sizeof(struct sockaddr_un)) == -1)handle_error("bind");if (listen(sfd, LISTEN_BACKLOG) == -1)handle_error("listen");/* Now we can accept incoming connections oneat a time using accept(2) */peer_addr_size = sizeof(struct sockaddr_un);cfd = accept(sfd, (struct sockaddr *) &peer_addr,&peer_addr_size);if (cfd == -1)handle_error("accept");/* Code to deal with incoming connection(s)... *//* When no longer required, the socket pathname, MY_SOCK_PATHshould be deleted using unlink(2) or remove(3) */}SEE ALSOaccept(2), connect(2), getsockname(2), listen(2), socket(2), getad‐drinfo(3), getifaddrs(3), ip(7), ipv6(7), path_resolution(7),socket(7), unix(7)COLOPHONThis page is part of release 4.04 of the Linux man-pages project. Adescription of the project, information about reporting bugs, and thelatest version of this page, can be found athttp://www.kernel.org/doc/man-pages/.Linux 2015-12-28 BIND(2)

函數原型:

#include <sys/types.h> /* See NOTES */ #include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);成功返回0,出錯返回-1

man中給的例程:

#include <sys/socket.h> #include <sys/un.h> #include <stdlib.h> #include <stdio.h> #include <string.h>#define MY_SOCK_PATH "/somepath" #define LISTEN_BACKLOG 50#define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0)intmain(int argc, char *argv[]){int sfd, cfd;struct sockaddr_un my_addr, peer_addr;socklen_t peer_addr_size;sfd = socket(AF_UNIX, SOCK_STREAM, 0);if (sfd == -1)handle_error("socket");memset(&my_addr, 0, sizeof(struct sockaddr_un));/* Clear structure */my_addr.sun_family = AF_UNIX;strncpy(my_addr.sun_path, MY_SOCK_PATH,sizeof(my_addr.sun_path) - 1);if (bind(sfd, (struct sockaddr *) &my_addr,sizeof(struct sockaddr_un)) == -1)handle_error("bind");if (listen(sfd, LISTEN_BACKLOG) == -1)handle_error("listen");/* Now we can accept incoming connections oneat a time using accept(2) */peer_addr_size = sizeof(struct sockaddr_un);cfd = accept(sfd, (struct sockaddr *) &peer_addr,&peer_addr_size);if (cfd == -1)handle_error("accept");/* Code to deal with incoming connection(s)... *//* When no longer required, the socket pathname, MY_SOCK_PATHshould be deleted using unlink(2) or remove(3) */}

服務器端和客戶端程序的顯著區別在于客戶端程序不需要調用bind函數,bind函數的作用是將套接字綁定一個IP地址和端口號,因為這兩個元素可以在網絡環境中唯一地址表示一個進程。如果套接字沒有使用bind函數綁定地址和端口,那么調用listen函數和connect函數的時候內核會自動為套接字綁定。由此可知,如果沒有使用bind函數,調用listen函數和connect函數的時候內核會自動為套接字綁定。看起來好像bind函數是多余的,但事實并不是這樣。

我們先來看看listen函數和connect是怎么綁定套接字的,connect函數綁定套接字的時候使用的是一個設置好的地址結構(sockaddr_in)作為參數,結構中指定了服務器的地址和需要通信的端口號。但是listen函數沒有這個參數,多以listen函數不能夠使用設置好的地址結構,只能由系統設置IP地址和端口號。也就是說在服務器端,如果不使用bind函數的話,創建套接字時使用的是當前系統中空閑端口的套接字。

這樣的話,服務器端的程序不關心客戶端的IP地址,也就說是對應的端口號是內核臨時指派的一個端口,是隨機的,每次執行服務器程序的時候,使用的都是不同的端口。但是在客戶端是需要指定通信的服務器的端口的,如果不使用bind函數,每次的端口是隨機的話,那么每次重啟服務程序之后都要對客戶端的程序進行調整,這樣做不僅不合理,而且工作量很大,因此在服務器端bind函數作用非常重要。
使用bind函數的歷程:

#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <strings.h> #include <ctype.h> #include <sys/socket.h> #include <arpa/inet.h> #define MAX_LINE 100int main(void) {struct sockaddr_in sin;struct sockaddr_in cin;int l_fd;int c_fd;socklen_t len;char buf[MAX_LINE];char addr_p[INET_ADDRSTRLEN];int port = 8000;int n;bzero(&sin, sizeof(sin));sin.sin_family = AF_INET;sin.sin_addr.s_addr = INADDR_ANY;sin.sin_port = htons(port);/*創立套接字,使用TCP協議*/if((l_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror("fail to creat socket");exit(1);}/*將地址和套節字綁定*/if(bind(l_fd, (struct sockaddr *) &sin, sizeof(sin)) == -1){perror("fail to bind");exit(1);}/*開始監聽連接請求*/if(listen(l_fd, 10) == -1){perror("fail to listren");exit(1);}printf("waiting...\n");while(1){/*接受連接請求,從此函數中返回后就可以開始通信了*/if((c_fd = accept(l_fd, (struct sockaddr *) &cin, &len)) == -1){perror("fail to accept");exit(1);}/*調用recv函數讀取客戶端傳來的信息,不設置任何特殊的標志*/n = recv(c_fd, buf, MAX_LINE, 0);if(n = -1){perror("fail to receive");exit(1);}else if(n == 0){printf("the connect has been closed\n ");close(c_fd);continue;}/*將客戶端地址轉換為字符串*/inet_ntop(AF_INET, &cin.sin_addr, addr_p, sizeof(addr_p));printf("client IP is %s, port is %s \n", addr_p, ntohs(cin.sin_port));printf("connect is : %s\n", buf);n = strlen(buf);sprintf(buf, "%d", n);/*使用send函數將轉換后的字符串發送給客戶端,不設置任何特殊的標志*/n = send(c_fd, buf, strlen(buf) + 1, 0);if(n == -1){perror("fail to send");exit(1);}if(cloes(c_fd) == -1){perror("fail to close");exit(1);}}return 0; }

總結

以上是生活随笔為你收集整理的bind函数详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。