为什么recvfrom关心数据来自谁

Why does recvfrom care about who the data comes from

因此,我正在使用 C 语言创建一个使用 UDP 的服务器,并且我想侦听来自多个来源的传入数据包。因此,当我调用 ssize_t recvfrom(int, void *, size_t, int, struct sockaddr * __restrict, socklen_t * __restrict) 时,包含发件人信息的第 5 个参数可能会有所不同。

有没有办法在不知道每个客户端的地址信息的情况下接收数据包?而且,这可能与 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");
}

我注意到当使用Java的DatagramSocket和DatagramPacket 类接收数据时,DatagramSocket的receive函数接受了一个DatagramPacket类型的参数。然而,这个 DatagramPacket 只包含放置数据的对象。那么,为什么C实现UDP接收需要知道发送方的信息呢?

Is there a way to receive the packets without knowing each individual client's address information?

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

来自man page,

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

[...] If the address argument is not a null pointer and the protocol provides the source address of messages, the source address of the received message shall be stored in the sockaddr structure pointed to by the address argument, and the length of this address shall be stored in the object pointed to by the address_len argument.

关于为什么部分,在无连接套接字的情况下,除非您知道通信中数据包的发送方地址,您不能回复 或回复发件人。因此,需要在无连接模式下专门了解发件人信息,并且 recvfrom() 与接收到的数据一起为我们提供了有关发件人的信息。


编辑:

在你的代码中

recvfrom(file_descriptor, data, strlen(data), 0, (struct sockaddr*)&iDontKnow, &addr_len)

是错误的,因为 strlen(data) 是 UB,因为您正在尝试计算未初始化的 char 数组的长度,该数组不符合 string .它调用 undefined behavior。您可能想使用 sizeof(data),因为 data 是一个数组。

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


此外,对于无连接套接字 (UDP),实际上需要获取发送者信息。对于面向连接的套接字,您还有另一个 stripped-down 替代方案,recv() 只负责接收和存储数据。

你可以这样做,

int sockfd_recv;
struct sockaddr_in recvaddr;
bzero(&recvaddr, sizeof(recvaddr));
recvaddr.sin_family = AF_INET;
recvaddr.sin_port = htons(port_recv);
recvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(sockfd_recv, (struct sockaddr *)&recvaddr, sizeof(recvaddr));

This DatagramPacket, however, only held the object in which to place the data.

以及源地址和端口,以及数据的长度。

So, why does C's implementation of UDP receiving require that you know the sender's information?

没有。它有选项告诉源地址和端口。这是一个结果参数,而不是输入。

你比较了 Java 和 C 的不同函数。 在 C 中还有一个不提供任何地址的 recv() 函数。 recvfrom 而不是 recv 的唯一目的是获取发件人的地址。 通常服务器会回复它们收到的数据包。没有不可能的地址。

如果您不关心数据包的发件人,只需 recv

或者反过来说: 如果您不关心发件人,为什么选择 recvfrom 版本 recv

我想知道如果服务器服务器不关心客户端的地址,它会做什么...但这与您的问题无关。