2017-03-01 46 views
1

因此,我创建了一个使用UDP的C服务器,并且我想监听来自多个源的传入数据包。因此,当我拨打ssize_t recvfrom(int, void *, size_t, int, struct sockaddr * __restrict, socklen_t * __restrict)时,包含发件人信息的第5个参数可能会有所不同。为什么recvfrom关心数据来自谁

有没有办法在不知道每个客户的地址信息的情况下接收数据包?而且,这可能与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接收实现要求你知道发送者的信息?

+1

您显示的代码在不知道个人客户端地址信息的情况下接收数据包!你的代码不需要知道发件人的信息(你永远不会用任何东西填充'iDontKnow'),它会工作得很好。 –

回答

5

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

那么,您无需事先知道发件人的信息。一旦接收到数据包,发送者信息(如果可用)将被存储到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); 

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

关于为什么部分,在连接插座的情况下,除非你知道发件人地址用于通信的数据包的,你不能回复或回复发件人。因此,需要在无连接模式下专门了解发件人信息,并且还有recvfrom(),它们与收到的数据一起给出了有关发件人的信息。


编辑:

在你的代码

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

是错误的,因为strlen(data)是UB,因为你想算一笔未初始化字符数组的长度,这是没有资格成为字符串。它调用undefined behavior。您可能需要使用sizeof(data),因为data是一个数组。

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


此外,对于无连接套接字(UDP),实际上它需要获取发件人信息。对于面向连接的套接字,您可以使用另一个精简的替代方案,recv()仅负责接收和存储数据。

+1

谢谢,我真的很感谢你的帮助! –

+0

@JeromeCarter不客气。 :) –

+0

哪个“相应”的说法? –

-2

你可以做到像这些,

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)); 
+1

建议您解释原因。 – user4581301

+1

而且,如何提供替代代码可以回答问题。 – EJP

1

DatagramPacket,但是,只有在举行用来放置数据的对象。

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

那么,为什么C的UDP接收实现要求您知道发件人的信息?

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

+0

感谢您的反馈! –

1

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

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

或者换句话说: 如果你不在意发件人,你为什么选择recvfrom版本的recv

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