3

我正在尝试创建一个基于数据报套接字(UDP)的迭代服务器。它调用连接到它从第一个 recvfrom() 调用获得的第一个客户端(是的,我知道这不是真正的连接)。在为这个客户端提供服务后,我断开 UDP 套接字(使用 AF_UNSPEC 调用连接)然后我调用 recvfrom() 从下一个客户端获取第一个数据包。

现在的问题是,在循环的第二次迭代中调用 recvfrom() 将返回 0。我的客户端从不发送空数据包,所以会发生什么。

这就是我正在做的事情(伪代码):

s = socket(PF_INET, SOCK_DGRAM, 0)

bind(s)

for(;;)
{
  recvfrom(s, header, &client_address)  // get first packet from client
  connect(s,client_address)  // connect to this client
  serve_client(s);
  connect(s, AF_UNSPEC); // disconnect, ready to serve next client
}

编辑:我发现我的客户端错误地发送了一个空包。现在我的问题是如何让客户端等待获得服务而不是向任何地方发送请求(服务器连接到另一个客户端并且不为任何其他客户端提供服务)。

4

3 回答 3

3

connect() 在 SOCK_DGRAM 上真的完全没有必要。

调用连接不会阻止您接收来自其他主机的数据包,也不会阻止您发送它们。只是不要打扰,它并没有真正的帮助。

更正:是的,显然它确实会阻止您接收来自其他主机的数据包。但是在服务器中执行此操作有点愚蠢,因为当您连接()到一个客户端时,任何其他客户端都会被锁定。此外,您仍然需要捕捉漂浮的“谷壳”。可能有一些与 DGRAM 套接字上的 connect() 相关的竞争条件 - 如果您调用 connect 并且来自其他主机的数据包已经在缓冲区中会发生什么?

此外,0 是 recvfrom() 的有效返回值,因为空(无数据)数据包是有效的并且可以存在(实际上,人们经常使用它们)。因此,您无法检查某事是否以这种方式成功。

很可能,队列中已经有一个零字节数据包。

你的协议应该被设计成最小化错误数据报被误解的机会;出于这个原因,我建议您不要使用空数据报,而是使用幻数。

UDP 应用程序必须能够识别“chaff”数据包并丢弃它们;他们迟早会出现。

于 2009-05-26T15:46:32.887 回答
0

man connect

...
如果启动套接字不是连接模式,则 connect()
应设置套接字的对等地址,并且不建立连接。
对于 SOCK_DGRAM 套接字,对等地址标识所有
数据报在随后的 send() 函数中发送,并且限制
后续 recv() 函数的远程发送者。如果地址
是协议的空地址,套接字的对等地址
应重置。
...
于 2009-05-26T15:52:13.420 回答
-1

只是一个更正,以防有人像我一样绊倒。要断开连接,需要调用 sockaddr 的 sa_family 成员设置为 AF_UNSPEC。不只是通过了AF_UNSPEC。

于 2015-06-01T21:37:56.200 回答