⟅UNIX网络编程⟆⦔bind函数

说在前面

基本说明

bind函数把一个本地协议地址(32位IPv4地址或128位IPv6地址与16位的TCP/UDP端口号的组合-网际协议)赋予一个套接字。

  • 定义

    #include <sys/socket.h>
    
    int bind(int sockfd, const struct sockaddr *address,
               socklen_t address_len);
    

    参数说明:

    • sockfd
      套接字描述符,即被绑定的套接字。
    • address
      指向特定协议的地址结构(见这里)的指针
    • address_len
      对应地址结构(见这里)的长度

    栗子:

    struct sockaddr_in	servaddr;
    /* ... */
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port        = htons(13);
    
    if(bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
    	err_sys("bind error");
    

    返回值:

    • 成功则返回0;否则返回-1并设置errno;常见的错误为EADDRINUSE,即“Address already in use”,地址已被使用。
  • IP地址和端口号

    在调用bind函数时可以同时指定IP地址和端口号(例如上面栗子中的sin_addr和sin_port),也可以仅指定IP地址、或者仅指定端口号,还可以都不指定。

    • 若TCP客户端/服务器调用bind时未指定端口,那么调用listen或者connect时,内核将选择一个临时端口。对于TCP客户端,这种情况十分常见;对于服务器,我们通常需要指定端口,客户端获取该端口号后进行连接。

      例外:远程过程调用(Remote Procedure Call)服务器。这种服务器由内核选定临时端口,然后该端口通过RPC端口映射器注册。客户在connect前必须通过端口映射器获取临时端口。

    • 进程可以把一个特定的IP地址捆绑到对应的套接字上,该IP地址必须为主机的某个网络接口(比如某块网卡,使用ifconfig/ipconfig命令)的IP。
      对于TCP客户端,这样的操作其实是指定了IP报文的源IP地址(通过哪个网络接口发送出去);但是客户端通常不绑定IP(一般不调用bind函数),内核会根据外出网络接口来选定源IP地址(比如要连接外网服务器,就不会选择环回地址
      对于TCP服务器,其实就是指定了接收哪一个网络接口的数据(IP数据报的目的IP必须是我们指定的IP)。如果服务器未绑定IP,那么内核会将客户发送的SYN报文的目的IP作为服务器的源IP地址(即服务器发送的数据报的源IP地址)

      进程指定结果
      IP地址端口
      通配地址0内核选择IP地址和端口
      通配地址非0内核选择IP地址,进程指定端口
      本地IP地址0进程指定IP地址,内核选择端口
      本地IP地址非0进程指定IP地址和端口

      注意:若让内核选定端口号,bind函数并不会返回内核选定的端口号值。为了得到这个值,我们需要使用getsockname函数

实际使用

  • 对于IPv4地址,通配地址通常为INADDR_ANY,其值一般为0。
    struct sockaddr_in servaddr;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
    INADDR_ANY是由主机序定义的,需要使用htonl进行转换(即使其值为0)。
  • 对于IPv6地址,
    #include <netinet/in.h>
    struct sockaddr_in6 servaddr;
    servaddr.sin6_addr = in6addr_any;
    
    in6addr_any为系统预先分配的变量,已经使用常值IN6ADDR_ANY_INIT对其进行了初始化。

其他

  • 进程捆绑非通配IP地址到套接字的常见栗子
    某个web服务器为多个组织提供服务。不同组织IP地址不同,但在同一个子网中(例如组织1为192.69.10.128,组织2为192.69.10.129);然后所有组织的IP都定义为单个网络接口的别名,这样IP层将接收到所有目的地址为其任何一个别名的数据报。每个组织仅需要绑定对应的IP地址即可。
    在这里插入图片描述
  • 另一种实现:捆绑通配地址的单个服务器。当一个连接到达时,通过getsockname获取客户的目的IP地址,服务器根据目的IP地址进行不同的处理。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值