为什么recvfrom关心数据来自何处

Jer*_*ter 1 c sockets udp network-programming recvfrom

所以,我在C中创建一个使用UDP的服务器,我想监听来自许多来源的传入数据包.因此,当我打电话时ssize_t recvfrom(int, void *, size_t, int, struct sockaddr * __restrict, socklen_t * __restrict),包含发件人信息的第五个参数可能会有所不同.

有没有办法在不知道每个客户的地址信息的情况下接收数据包?而且,这可能与C的库有关吗?

这是我的代码:

int file_descriptor;
char data[1024];
int bytes_recved;
sockaddr_in iDontKnow;
socklen_t addr_len = sizeof(iDontKnow);
if ((bytes_recved = recvfrom(file_descriptor, data, strlen(data), 0, (struct sockaddr*)&iDontKnow, &addr_len)) < 0) {
    perror("Failed to receive data");
}
Run Code Online (Sandbox Code Playgroud)

我注意到,当使用Java的DatagramSocket和DatagramPacket类接收数据时,DatagramSocket的receive函数接受了DatagramPacket 类型的参数.但是,此DatagramPacket仅保存放置数据的对象.那么,为什么C的UDP接收实现要求您知道发送者的信息?

Sou*_*osh 5

有没有办法在不知道每个客户的地址信息的情况下接收数据包?

好吧,无论如何,您无需事先知道发件人信息.收到数据包后,将存储发件人信息(如果有)address.

手册页中,

ssize_t recvfrom(int socket, void *restrict buffer, size_t length,
                   int flags, struct sockaddr *restrict address,
                   socklen_t *restrict address_len);
Run Code Online (Sandbox Code Playgroud)

[...]如果address参数不是空指针且协议提供消息的源地址,则接收消息的源地址应存储在sockaddraddress参数指向的结构中,并且该地址的长度应存储在address_len参数指向的对象中.

关于为什么部分,在无连接套接字的情况下,除非您知道通信中的数据包的发件人地址,否则您无法回复或回复发件人.因此,需要在无连接模式下专门知道发件人信息,并且随之而来的是recvfrom()与收到的数据一起向我们提供有关发件人的信息.


编辑:

在你的代码中

recvfrom(file_descriptor, data, strlen(data), 0, (struct sockaddr*)&iDontKnow, &addr_len)
Run Code Online (Sandbox Code Playgroud)

是错误的,就像strlen(data)UB一样,因为你试图计算未初始化的char数组的长度,该数组不符合字符串的条件.它调用未定义的行为.您可能想要使用sizeof(data),就像data数组一样.

如果您对发件人的信息不感兴趣,只需将a NULL作为相应的参数传递.


除此之外,对于无连接套接字(UDP),实际上需要获取发件人信息.对于面向连接的套接字,您有另一种精简替代方案,recv()它只负责接收和存储数据.