当我们使用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;
}
运行结果: