当我们使用socket创建一个套接口时,并没有为它分配地址,bind函数给套接口指定一个本机地址,Internet是IP和PORT的组合。
函数bind既可以用于面向连接的socket也可以用于无连接的socket,它要在connect和listen之前调用。
函数原型:
int WSAAPI bind(SOCKET s,const struct sockaddr FAR* name,int namelen);
成功返回0,失败返回SOCKET_ERROR。
第二个参数name是一个指向“sockaddr”结构的指针,这是一个通用的地址结构,它的域成员sa_family指明协议对应的地址簇,不同
的协议簇可以使用不同的地址格式,网络协议根据sa_family对“sockaddr”结构做出正确解释。编程时使用与协议相关的地址结构,但在
传递给socket接口函数时,需要把它转换成通用socket地址结构,WinSock提供的API中凡使用到地址的函数都是用这个结构,为用户
提供了统一接口。
internet协议地址包括三个部分:地址簇、主机地址、端口号。地址簇sa_family为常量AF_INET。当应用程序不关心本地地址时,它
可以把地址设置为INADDR_ANY,由底层网络协议模块为程序选择一个合适的地址,在多宿主机上简化了应用程序的设计。应用程序如果
不调用bind,当它调用connect和listen时,系统会为socket选择本地地址和临时端口。这对客户端是非常正常的行为,除非应用程序对端口
有特殊要求。但是对服务器,使用临时端口是非常少见的,它通常绑定在知名端口上,这样大家才能访问到服务器。
测试程序:
#include<stdio.h> #include<winsock2.h> #pragma comment(lib,"ws2_32.lib") //winsock 使用的库函数 #define BIND_DEF_PORT htons(6000) //默认端口 #define BIND_DEF_ADDR inet_addr("127.0.0.1") struct port_addr_s { unsigned short port; unsigned long addr; }; int main() { WSADATA wsaData; SOCKET sock = 0; //Socket句柄 int result = 0,i,count,addr_len; struct sockaddr_in laddr,taddr; //Socket的本机地址 struct port_addr_s port_addr[] = { {0,INADDR_ANY}, {BIND_DEF_PORT,INADDR_ANY}, {0,BIND_DEF_ADDR}, {BIND_DEF_PORT,BIND_DEF_ADDR} }; WSAStartup(MAKEWORD(2,0),&wsaData); //初始化 count = sizeof(port_addr) / sizeof(port_addr[0]); for(i = 0; i < count; i++) { memset(&laddr,0,sizeof(laddr)); //作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法 laddr.sin_family = AF_INET; laddr.sin_port = port_addr[i].port; laddr.sin_addr.s_addr = port_addr[i].addr; addr_len = sizeof(struct sockaddr_in); sock = socket(AF_INET,SOCK_STREAM,0); //创建Socket result = bind(sock,(struct sockaddr*)&laddr,addr_len); if(result == SOCKET_ERROR) { printf("[bind]error = %d\r\n",WSAGetLastError()); continue; } result = getsockname(sock,(struct sockaddr *)&taddr,&addr_len); //得到实际绑定到的地址和端口并打印出来 if(result == 0) //成功 printf("[bind]address = %s:%d\r\n",inet_ntoa(taddr.sin_addr),ntohs(taddr.sin_port)); else printf("[bind]error = %d\r\n",WSAGetLastError()); closesocket(sock); } WSACleanup(); return 0; }
运行结果: