UDP服务器和连接的套接字

UDP服务器和连接的套接字,udp,bind,connect,Udp,Bind,Connect,[编辑] 似乎我的问题是近10年前在这里提出的 …没有干净且可扩展的解决方案。我认为这可以通过支持UDP的listen()和accept()轻松解决,就像现在的connect()一样。 [/编辑] 在这个问题的后续行动中 …是否存在同时绑定()和连接()的机制 我询问的原因是多线程UDP服务器可能希望将新的“会话”移动到其自己的描述符,以实现可伸缩性。其目的是防止侦听器描述符成为瓶颈,类似于SO_REUSEPORT背后的原理 但是,在执行connect()调用之前,使用新描述符的bind()

[编辑] 似乎我的问题是近10年前在这里提出的

…没有干净且可扩展的解决方案。我认为这可以通过支持UDP的listen()和accept()轻松解决,就像现在的connect()一样。 [/编辑]

在这个问题的后续行动中

…是否存在同时绑定()和连接()的机制

我询问的原因是多线程UDP服务器可能希望将新的“会话”移动到其自己的描述符,以实现可伸缩性。其目的是防止侦听器描述符成为瓶颈,类似于SO_REUSEPORT背后的原理

但是,在执行connect()调用之前,使用新描述符的bind()调用将从侦听器描述符接管端口。这为入口数据报传递到新的描述符队列提供了一个机会窗口,尽管时间很短

对于希望使用DTL的UDP服务器来说,此窗口也是一个问题。如果客户端重试,它是可恢复的,但不必重试会更好。

connect()
在UDP上不提供连接多路复用

connect()
做两件事:

  • 为不接受目标地址的传输函数设置默认地址(
    send()
    write()
    ,等等)

  • 设置传入数据报的筛选器

  • 重要的是要注意,传入筛选器只是丢弃不匹配的数据报。它不会将它们转发到其他地方。如果有多个UDP套接字绑定到同一地址,一些操作系统会为每个数据报选择一个(可能是随机的,可能是最后创建的)(解复用完全中断),一些操作系统会将所有数据报传递给所有这些数据报(解复用成功,但效率极低)。这两个都是“错误的事情”。即使是一个允许您通过套接字选项在这两种行为之间进行选择的操作系统,其操作方式仍然与您希望的不同。
    bind()
    connect()
    之间的时间只是这个不想要的行为之谜中最小的一块

    要处理多个对等方的UDP,在无连接模式下使用单个套接字。要让多个线程并行处理接收到的数据包,您可以

    • 在处理数据的多个线程上调用
      recvfrom
      (这是有效的,因为数据报套接字保留消息边界,您永远不会使用流套接字(如TCP)这样做),或者
    • 在单个线程上调用
      recvfrom
      ,它不做任何处理,只是将消息排入负责处理它的线程的队列

    即使您有一个操作系统,允许您根据指定的对等地址(连接模拟)调度传入UDP,在操作系统内进行调度也不会比在服务器应用程序中进行调度更有效,而且,针对您的流量模式进行调优的用户空间调度器可能会比操作系统提供的“一刀切”调度器表现得更好

    例如,DNS(DHCP)服务器将与许多不同的主机进行交易,几乎所有主机都运行在远程端的端口53(67-68)上。因此,基于远程端口的哈希将是无用的,您需要在主机上进行哈希。相反,支持web应用服务器集群的缓存服务器将与少量主机和大量不同端口进行事务处理。在这里,在远程端口上进行散列将更好

    自己进行连接关联,不要使用套接字连接模拟。

    connect()
    在UDP上不提供连接解复用

    connect()
    做两件事:

  • 为不接受目标地址的传输函数设置默认地址(
    send()
    write()
    ,等等)

  • 设置传入数据报的筛选器

  • 重要的是要注意,传入筛选器只是丢弃不匹配的数据报。它不会将它们转发到其他地方。如果有多个UDP套接字绑定到同一地址,一些操作系统会为每个数据报选择一个(可能是随机的,可能是最后创建的)(解复用完全中断),一些操作系统会将所有数据报传递给所有这些数据报(解复用成功,但效率极低)。这两个都是“错误的事情”。即使是一个允许您通过套接字选项在这两种行为之间进行选择的操作系统,其操作方式仍然与您希望的不同。
    bind()
    connect()
    之间的时间只是这个不想要的行为之谜中最小的一块

    要处理多个对等方的UDP,在无连接模式下使用单个套接字。要让多个线程并行处理接收到的数据包,您可以

    • 在处理数据的多个线程上调用
      recvfrom
      (这是有效的,因为数据报套接字保留消息边界,您永远不会使用流套接字(如TCP)这样做),或者
    • 在单个线程上调用
      recvfrom
      ,它不做任何处理,只是将消息排入负责处理它的线程的队列

    即使您有一个操作系统,允许您根据指定的对等地址(连接模拟)调度传入UDP,在操作系统内进行调度也不会比在服务器应用程序中进行调度更有效,而且,针对您的流量模式进行调优的用户空间调度器可能会比操作系统提供的“一刀切”调度器表现得更好

    例如,DNS(DHCP)服务器将与许多不同的主机进行交易,几乎所有主机都运行在远程端的端口53(67-68)上。因此,基于远程端口的哈希将是无用的,您需要在主机上进行哈希。相反,支持web应用服务器集群的缓存服务器正在运行