日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

bind函数详解

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

看看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)

函數(shù)原型:

#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) */}

服務(wù)器端和客戶端程序的顯著區(qū)別在于客戶端程序不需要調(diào)用bind函數(shù),bind函數(shù)的作用是將套接字綁定一個IP地址和端口號,因為這兩個元素可以在網(wǎng)絡(luò)環(huán)境中唯一地址表示一個進(jìn)程。如果套接字沒有使用bind函數(shù)綁定地址和端口,那么調(diào)用listen函數(shù)和connect函數(shù)的時候內(nèi)核會自動為套接字綁定。由此可知,如果沒有使用bind函數(shù),調(diào)用listen函數(shù)和connect函數(shù)的時候內(nèi)核會自動為套接字綁定??雌饋砗孟馼ind函數(shù)是多余的,但事實并不是這樣。

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

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

#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);/*創(chuàng)立套接字,使用TCP協(xié)議*/if((l_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){perror("fail to creat socket");exit(1);}/*將地址和套節(jié)字綁定*/if(bind(l_fd, (struct sockaddr *) &sin, sizeof(sin)) == -1){perror("fail to bind");exit(1);}/*開始監(jiān)聽連接請求*/if(listen(l_fd, 10) == -1){perror("fail to listren");exit(1);}printf("waiting...\n");while(1){/*接受連接請求,從此函數(shù)中返回后就可以開始通信了*/if((c_fd = accept(l_fd, (struct sockaddr *) &cin, &len)) == -1){perror("fail to accept");exit(1);}/*調(diào)用recv函數(shù)讀取客戶端傳來的信息,不設(shè)置任何特殊的標(biāo)志*/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;}/*將客戶端地址轉(zhuǎn)換為字符串*/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函數(shù)將轉(zhuǎn)換后的字符串發(fā)送給客戶端,不設(shè)置任何特殊的標(biāo)志*/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; }

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。