Select 模拟UDP的accept()(设置解复用UDP套接字时的计时问题)
对于具有长寿命连接的UDP服务器体系结构,一种体系结构是使用一个套接字侦听所有传入的UDP通信,然后使用connect()为每个连接创建单独的套接字以设置远程地址。我的问题是,是否有可能像accept()对TCP所做的那样在原子上实现这一点 创建一个单独的套接字并使用connect()的原因是,这样可以很容易地将数据包处理扩展到多个线程,也可以更容易地使套接字与处理所需的数据结构直接关联。 网络堆栈中的解复用逻辑将传入数据包路由到最特定的套接字 现在,我的问题是,如果要模拟UDP的accept(),会发生什么情况,如下所示:Select 模拟UDP的accept()(设置解复用UDP套接字时的计时问题),select,udp,Select,Udp,对于具有长寿命连接的UDP服务器体系结构,一种体系结构是使用一个套接字侦听所有传入的UDP通信,然后使用connect()为每个连接创建单独的套接字以设置远程地址。我的问题是,是否有可能像accept()对TCP所做的那样在原子上实现这一点 创建一个单独的套接字并使用connect()的原因是,这样可以很容易地将数据包处理扩展到多个线程,也可以更容易地使套接字与处理所需的数据结构直接关联。 网络堆栈中的解复用逻辑将传入数据包路由到最特定的套接字 现在,我的问题是,如果要模拟UDP的accept(
你有两个简单的选择
- 扩展协议,使源在某个固定端口上接受传入连接,然后继续协议通信。在这种情况下,您可以让源请求位于标准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后面的客户端。好的,我不知道您愿意在套接字层下编码。