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 套接字发送到隐式绑定的主要内容,如果未能解决你的问题,请参考以下文章