Visual C++网络编程(黑客)学习笔记三
创建了Socket后,套接字数据结构中有一个默认的IP地址和默认的端口号。服务器端程序必须调用bind函数来为其绑定一个IP地址和一个特定的端口号,这样客户端才知道要连接服务器端的哪个IP地址的哪个端口号。客户端程序一般不必调用bind函数来为其Socket绑定IP地址和端口号。该函数调用成功返回0,否则返回SOCKET_ERROR.
bind函数原型:
int bind(
SOCKET s,
const struct sockaddr FAR *name,
int namelen
);
函数参数解释:
s:指定待绑定的Socket描述符。
name:指定一个sockaddr结构。
namelen:是name结构体的大小。
name是一个sockaddr结构类型,sockaddr结构类型定义如下。参数sa_family指定地址族,对于TCP/IP族的套接字,将其设置为AF_INET.
struct sockaddr(
u_short sa_family;
char sa_data[14];
);
对于TCP/IP族的套接字进行绑定时,通常使用另一个地址结构:
struct sockaddr_in(
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
);
函数参数解释:
sin_family:设置TCP/IP协议族类型AF_INET.
sin_port:指定端口号。
sin_addr:结构体中只有一个唯一的字段s_addr,表示IP地址,该字段是一个整数,一般用函数inet_addr()把字符串形式的IP转换成unsigned long型的整数值后再发送给s_addr.
提示:有的服务器是多宿主机,一般有两个网卡。运行在这样的服务器上的服务器端程序在为其Socket绑定IP地址时可以把htonl(INADDR_ANY)置给s_addr。好处是不管那个网段上的客户端程序都能与该服务端程序通信。如果只给运行在多宿主机上的服务器端程序的Socket绑定一个固定的IP地址,那么只有与该IP地址处于同一个网段上的客户端程序才能与该服务器端程序通信。使用0来填充sin_zero数组,目的是让sockaddr_in结构的大小与sockaddr结构的大小保持一致。
下面是一个bind函数调用的例子.
//......
struct sockaddr_in name;
name.sin_family = AF_INET;
name.sin_port = htons(80);
name.sin_addr.s_addr = htonl(INADDR_ANY);
int namelen = sizeof(name);
bind(sSocket, (struct sockaddr *)&name, namelen);
//......
以上代码中,如果不需要特别指明IP地址和端口号的值,那么可以设定IP地址为INADDR_ANY,Port为0。Windows Sockets会自动为其设定适当的IP地址和Port(1024——5000)。如果想得到该IP地址和端口,可以调用getsockname()函数来获得其被设定的值。
