udp 套接字发送到隐式绑定

Posted

技术标签:

【中文标题】udp 套接字发送到隐式绑定【英文标题】:udp socket sendto implicit bind 【发布时间】:2019-01-30 15:17:07 【问题描述】:

我在这里查看 udp 客户端示例: http://www.linuxhowtos.org/data/6/client_udp.c

sn-p:

/* UDP client in the internet domain */
   struct sockaddr_in server, from;
   //...snipped

   sock= socket(AF_INET, SOCK_DGRAM, 0);
   if (sock < 0) error("socket");

   server.sin_family = AF_INET;
   hp = gethostbyname(argv[1]);
   if (hp==0) error("Unknown host");

   bcopy((char *)hp->h_addr, 
        (char *)&server.sin_addr,
         hp->h_length);
   server.sin_port = htons(atoi(argv[2]));
   length=sizeof(struct sockaddr_in);

   //... snipped       

   n=sendto(sock,buffer,
            strlen(buffer),0,(const struct sockaddr *)&server,length);
   if (n < 0) error("Sendto");
   n = recvfrom(sock,buffer,256,0,(struct sockaddr *)&from, &length);
   if (n < 0) error("recvfrom");
   //... snipped    

我试图了解它是如何知道从哪里接收消息的。我知道当sendto 被调用时,选择了一个可用端口并将其嵌入到 udp 消息中,服务器应用程序可以读取并回复它。客户端代码如何知道在该端口上接收消息?

这个答案:https://***.com/a/48245273/2748602 表示在调用 sendto 函数时存在某种隐式绑定。它是如何工作的?它实际上是与随机可用端口号的绑定,就像我调用bind 或其他东西一样永久?似乎有一些永久性的方面。只是对更多细节感兴趣。

【问题讨论】:

另一端可能正在使用recvfrom,它给出了发件人的地址/端口对,并将其用于回复。 "它实际上是一个具有随机可用端口号的绑定,就像我调用了绑定一样永久" - 这正是发生的事情 【参考方案1】:

如果套接字未绑定,则 是一个隐式绑定,因为所有数据包都必须同时携带一个源端口。因此,API 假设如果您事先对绑定套接字的端口不够关心,那么它可以将套接字绑定到随机端口。虽然很遗憾我不知道sendto 的实现细节,但我可以提供一些官方文档。

对于 Linux,来自udp man page:

当一个 UDP 套接字被创建时,它的本地地址和远程地址是 未指定。可以使用 sendto(2) 或立即发送数据报 sendmsg(2) 以有效的目标地址作为参数。什么时候 在套接字上调用 connect(2),默认目标 地址已设置,现在可以使用 send(2) 或 write(2) 发送数据报 没有指定目标地址。还是可以的 通过将地址传递给 sendto(2) 或 发送消息(2)。 为了接收数据包,可以将套接字绑定到一个 本地地址首先使用 bind(2)。 *否则,socket层 将自动分配一个超出定义范围的空闲本地端口 通过 /proc/sys/net/ipv4/ip_local_port_range 并将套接字绑定到 INADDR_ANY

对于 Windows,Winsock 2's sendto 文档中的 sn-p:

如果套接字未绑定,则将唯一值分配给本地 由系统关联,然后将套接字标记为已绑定。如果 套接字已连接,getsockname 函数可用于 确定与套接字关联的本地 IP 地址和端口。

【讨论】:

【参考方案2】:

... 调用 sendto 函数时存在一种隐式绑定。它是如何工作的?它实际上是一个具有随机可用端口号的绑定,就像我调用了 bind 或其他东西一样永久?

man ip(7):

   ip_local_port_range (since Linux 2.2)
          This file contains two integers that define the default local
          port range allocated to sockets that are not explicitly bound
          to a port number—that is, the range used for ephemeral ports.
          An ephemeral port is allocated to a socket in the following
          circumstances:

          *  the port number in a socket address is specified as 0 when calling bind(2);

          *  listen(2) is called on a stream socket that was not previously bound;

          *  connect(2) was called on a socket that was not previously bound;

          *  sendto(2) is called on a datagram socket that was not previously bound.

【讨论】:

"当一个临时端口被分配时"...它是通过调用bind来分配的吗?

以上是关于udp 套接字发送到隐式绑定的主要内容,如果未能解决你的问题,请参考以下文章

【奇】udp的recvfrom

Linux学习_UDP编程

UDP发送数据示例

UDP发送数据示例

重新绑定 UDP 套接字

Alpakka UDP:如何通过已绑定的套接字响应收到的数据报?