udp套接字sendto隐式绑定

时间:2019-01-30 15:17:07

标签: c++ linux sockets

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

摘要:

/* 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://stackoverflow.com/a/48245273/2748602表示调用sendto函数时存在某种隐式绑定。它是如何工作的?实际上,它是否是具有一个随机可用端口号的绑定,而该端口号就像我曾经叫过bind一样永久存在?似乎存在永久性的某些方面。只是对更多细节感兴趣。

2 个答案:

答案 0 :(得分:1)

如果套接字未绑定,则隐式绑定,因为所有数据包都必须同时承载两个源端口。因此,API假定,如果您对端口预先绑定的端口并不十分在意,则可以将套接字绑定到随机端口。而且,不幸的是,我不知道sendto的实现细节,我可以提供一些官方文档。

对于Linux,请从udp man page

  

创建UDP套接字后,其本地和远程地址为   未指定。数据报可以使用sendto(2)或   sendmsg(2),带有有效的目标地址作为参数。什么时候   在套接字(默认目标)上调用connect(2)   设置了地址,现在可以使用send(2)或write(2)发送数据报   而不指定目标地址。仍然有可能   通过将地址传递到sendto(2)来发送到其他目的地,或者   sendmsg(2)。 为了接收数据包,可以将套接字绑定到   首先使用bind(2)本地地址。 *否则,套接字层   将自动分配超出定义范围的空闲本地端口   通过/ proc / sys / net / ipv4 / ip_local_port_range并将套接字绑定到   INADDR_ANY

对于Windows,是Winsock 2's sendto文档的摘录:

  

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

答案 1 :(得分:0)

  

...调用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.