断开并重新连接已连接的数据报插槽

时间:2009-05-26 15:40:35

标签: networking sockets udp posix datagram

我试图创建一个基于数据报套接字(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
}
编辑:我发现我的客户端中的错误意外地发送了一个空数据包。 现在我的问题是如何使客户端等待服务而不是发送请求(服务器连接到另一个客户端,并且还没有服务任何其他客户端)。

3 个答案:

答案 0 :(得分:3)

在SOCK_DGRAM上,

connect()完全没必要。

调用connect 不会阻止您从其他主机接收数据包,也不会阻止您发送它们。只是不要打扰,这不是真的有用。

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

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

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

应该设计您的协议,以尽量减少错误数据报被误解的可能性;因此我建议你不要使用空数据报,而是使用幻数。

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

答案 1 :(得分:0)

man connect

...
If the initiating socket is not connection-mode, then connect()
shall set the socket’s peer address, and no connection is made.
For SOCK_DGRAM sockets, the peer address identifies where all
datagrams are sent on subsequent send() functions, and limits
the remote sender for subsequent recv() functions. If address
is a null address for the protocol,  the  socket’s  peer  address
shall be reset.
...

答案 2 :(得分:-1)

只是纠正,以防任何人像我一样绊倒这个。要断开connect(),需要将sockaddr的sa_family成员设置为AF_UNSPEC来调用。不只是通过AF_UNSPEC。