Select 模拟UDP的accept()(设置解复用UDP套接字时的计时问题)

Select 模拟UDP的accept()(设置解复用UDP套接字时的计时问题),select,udp,Select,Udp,对于具有长寿命连接的UDP服务器体系结构,一种体系结构是使用一个套接字侦听所有传入的UDP通信,然后使用connect()为每个连接创建单独的套接字以设置远程地址。我的问题是,是否有可能像accept()对TCP所做的那样在原子上实现这一点 创建一个单独的套接字并使用connect()的原因是,这样可以很容易地将数据包处理扩展到多个线程,也可以更容易地使套接字与处理所需的数据结构直接关联。 网络堆栈中的解复用逻辑将传入数据包路由到最特定的套接字 现在,我的问题是,如果要模拟UDP的accept(

对于具有长寿命连接的UDP服务器体系结构,一种体系结构是使用一个套接字侦听所有传入的UDP通信,然后使用connect()为每个连接创建单独的套接字以设置远程地址。我的问题是,是否有可能像accept()对TCP所做的那样在原子上实现这一点

创建一个单独的套接字并使用connect()的原因是,这样可以很容易地将数据包处理扩展到多个线程,也可以更容易地使套接字与处理所需的数据结构直接关联。 网络堆栈中的解复用逻辑将传入数据包路由到最特定的套接字

现在,我的问题是,如果要模拟UDP的accept(),会发生什么情况,如下所示:

  • 将select()与包含UDP服务器套接字的fd集一起使用

  • 然后从UDP服务器套接字读取数据包

  • 然后创建一个新的UDP套接字,然后将其连接到远程地址

  • 我使用包含两个套接字的fd集调用select()

  • 归还什么

  • 假设数据包到达操作系统的时间介于1和3之间

    数据包将被解复用到UDP服务器套接字,还是将被解复用到3中创建的更具体的套接字。也就是说,解复用在什么时候发生?当数据包到达时,还是必须“好像”到达第4点

    如果上述方法不起作用,请跟进问题:最好的方法是什么?

    这将不起作用。
    你有两个简单的选择

  • 创建一个多线程程序,该程序有一个“根”线程监听UDP套接字,并根据源将收到的数据包“分派”到正确的线程。这是因为您希望按源隔离处理

    • 扩展协议,使源在某个固定端口上接受传入连接,然后继续协议通信。在这种情况下,您可以让源请求位于标准UDP端口(由您选择),然后您的终端将从新的UDP套接字响应源的UDP端口。这样,您就启动了一个新的UDP路径,从您的终端向后到每个源的已知UDP端口。这样,您的终端就有了不同的UDP套接字

  • 我知道这个讨论是从2009年开始的,但由于它在我搜索时不断出现,我认为我应该分享我的方法。这既是为了得到一些反馈,也是因为我对问题的作者如何解决这个问题很好奇

    我选择模仿UDP接受的方式是nik答案中的第一和第二个组合。我有一个根线程,它监听给定的套接字。为了简单起见,我选择使用TCP,但将此套接字更改为UDP并不困难。当客户端希望使用UDP“连接”到我的服务器时,它首先连接到TCP套接字并请求新的连接

    然后,根线程继续创建UDP套接字,将其绑定到本地接口,进行连接并设置数据结构。然后将该文件描述符传递给负责连接的线程。新UDP套接字的IP/端口信息被传递回客户端,客户端创建一个新的UDP套接字并将数据发送到提供的IP/端口


    这种方法在我的使用中效果很好,但是设置流的附加步骤会带来开销。在某些情况下,这种开销可能是不可接受的

    我在这里自己问了这个问题后发现了这个问题

    由于connect()可用于UDP指定对等地址,我想知道为什么accept()不能用于从服务器端有效地完成连接的UDP会话。它甚至可以将触发accept()的数据报(以及来自同一客户机的任何其他数据报)移到新的描述符上


    这将实现更好的服务器可伸缩性(请参阅SO_REUSEPORT背后的原理了解更多背景信息),以及可靠的DTLS身份验证。

    您确定您甚至可以创建一个新的UDP套接字连接到另一端,并且仍然保持相同的服务器端端口吗?您通常要做的是在服务器端的不同端口上创建一个UDP套接字,“服务器套接字”仅用于初始请求,与对等方的进一步通信在两个完全不同的端口上进行。或者只需在服务器上使用1个套接字,而不需要连接它,只需注意对等方的地址。UPD是无连接的,为什么不起作用?有关将解复用到最特定套接字的操作系统的示例,请参阅。我对您提出的解决方案的问题是,解决方案1可能无法扩展,并且解决方案2生成的数据包可能无法到达特定NAT后面的客户端。好的,我不知道您愿意在套接字层下编码。