bind函数的用法和参数(go网络编程)

基本TCP客户端/服务器程序套接字函数

1、bind函数将本地协议地址赋予套接字。 对于互联网协议,协议地址是32位IPv4地址或128位IPv6地址与16位TCP或UDP端口号的组合。

#includesys/socket.h

intbind(intsockfd,const struct sockaddr,socklen_t addrlen );

第二个参数是指向特定协议地址结构的指针,第三个参数是该地址结构的长度。 对于TCP,要调用bind函数,可以指定端口号、指定IP地址,或者两者都不指定。

服务器在启动时捆绑众所周知的端口。 如果TCP客户端或服务器没有通过调用bind绑定端口,则在调用connect或listen时,内核必须选择相应套接字的临时端口。 除非APP应用程序需要保留端口,否则让内核选择临时端口对TCP客户来说是很正常的。 但是,TCP服务器非常罕见,因为它通过众所周知的端口被识别。 进程可以将特定的IP地址与套接字捆绑在一起,但IP地址必须属于该IP地址所在的网络接口之一。 对于TCP客户端,源IP地址被分配给在套接字上发送的IP数据报。 对于服务器,套接字被限制为只能接收目标具有此IP地址的客户端连接。 TCP客户端通常不将IP地址与套接字绑定。 连接到套接字后,内核将根据使用的出站网络接口选择源IP地址,而使用的出站接口取决于到达服务器所需的路径。 在套接字绑定了将不会在TCP服务器上的IP地址时,内核将客户端发送的SYN的目标IP地址作为服务器的源IP地址。

下面的图4-6总结了根据预期结果设置sin_addr和sin_port或sin6_addr和sin6_port值的方法

如果将端口号指定为0,则内核在调用bind时选择临时端口。 但是,如果将IP地址指定为公用地址,则内核将在套接字连接或套接字发出数据报后才选择本地IP地址。

对于IPv4,分配地址通常由INADDR_ANY指定,其值通常为0。 指示内核选择IP地址。

struct sockaddr_in servaddr;

servaddr.sin _ addr.s _ addr=htonl (in addr _ any );

这样的赋值对于IPv4是可能的。 这是因为IP地址是32位的值,能够用简单的数值常数表示。 在IPv6的情况下,由于128位的IPv6地址被存储在结构体中,所以不能进行这种操作。

struct sockaddr_in6 serv;

serv.sin6_addr=in6addr_any;

in6addr_any变量被预分配并初始化为常数值IN6ADDR_ANY_INIT。 头文件netinet/in.h中包含in6addr_any的扩展声明。

无论是网络的字节序还是主机的字节序,INADDR_ANY的值(0)都相同,因此无需使用htonl。 但是,头文件netinet/in.h中定义的所有INADDR_常量都是根据主机的字节顺序定义的,因此这些常量必须使用htonl。

请注意,如果要让内核选择套接字的临时端口号,函数bind不会返回选定的值。 实际上,bind函数的第二个参数具有const限定词,因此无法返回选定的值。 要获取内核选择的此临时端口的值,必须调用函数getsockname返回协议地址。

将非通配符IP地址与套接字绑定的过程的一个典型示例是向多个组织提供Web服务器的主机。 首先,每个组织都必须有自己的域名。 例如,它的形式类似于www.baidu.com。 然后,每个组织的域名映射到不同的地址,但通常位于同一子网中。 例如,如果子网为198.69.10,则第一个组织的IP地址为198.69.10.128,第二个IP地址为198.69.10.129,依此类推。 然后,将所有这些IP地址定义为单个网络接口的别名。 例如,在4.4BSD系统中,使用ifconfig命令的alias选项进行定义。 这样,IP层就会接收所有目标都是别名地址的外部数据报。 最后,为每个组织启动HTTP服务器的副本。 每个副本仅捆绑有组织的IP地址。

bind函数返回的一个常见错误是eaddrinuse。 地址” addressalreadyinuse “地址已被使用。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注