【问题标题】:UDP packets arriving on wrong sockets on LinuxUDP 数据包到达 Linux 上的错误套接字
【发布时间】:2019-01-08 20:25:27
【问题描述】:

我有两个 UDP 套接字绑定到同一个地址并连接到地址 A 和 B。我还有两个 UDP 套接字绑定到 A 和 B 但未连接。

这就是我的/proc/net/udp 的样子(为了便于阅读而进行了修剪):

  sl  local_address rem_address
 3937: 0100007F:DD9C 0300007F:9910
 3937: 0100007F:DD9C 0200007F:907D
16962: 0200007F:907D 00000000:0000
19157: 0300007F:9910 00000000:0000

根据connect(2)“如果socket sockfd的类型是SOCK_DGRAM,那么addr就是默认发送数据报的地址,是接收数据报的唯一地址。”

由于某种原因,我连接的套接字正在接收发往彼此的数据包。 eg:连接到A的UDP套接字向A发送消息,然后A返回回复。连接到 B 的 UDP 套接字向 B 发送消息,然后 B 发送回复。但是来自 A 的回复到达连接到 B 的套接字,而来自 B 的回复到达连接到 A 的套接字。

到底为什么会发生这种情况?请注意,它是随机发生的——有时回复到达正确的套接字,有时却没有。有什么方法可以防止这种情况或connect 应该不起作用的任何情况?

【问题讨论】:

标签: linux sockets udp ip


【解决方案1】:

嗯,据我所知,没有订购保证。

来自手册页:

      SO_REUSEPORT (since Linux 3.9)
              Permits multiple AF_INET or AF_INET6 sockets to be bound to an identical socket address.  This option must be set on each socket (including the first socket) prior to calling bind(2) on the socket.  To prevent port  hijacking,  all
              of the processes binding to the same address must have the same effective UID.  This option can be employed with both TCP and UDP sockets.

              For  TCP  sockets,  this  option allows accept(2) load distribution in a multi-threaded server to be improved by using a distinct listener socket for each thread.  This provides improved load distribution as compared to traditional
              techniques such using a single accept(2)ing thread that distributes connections, or having multiple threads that compete to accept(2) from the same socket.

              For UDP sockets, the use of this option can provide better distribution of incoming datagrams to multiple processes (or threads) as compared to the traditional technique of having multiple processes compete to receive datagrams  on
              the same socket.

因此,您使用的东西主要被视为服务器(或在某些情况下为客户端,但无法保证排序 - 特别是在 UDP 中)作为客户端的选项。

我怀疑你的方法是错误的,需要重新考虑 =)

PS。只是快速浏览了一下,但恕我直言,这是您方法中的一个错误

【讨论】:

  • 套接字已连接的事实意味着它们应该只从它们所连接的地址接收数据报。至少根据man connect.
  • UDP 不跟踪会话,数据包将被传递到任一进程 - 这是我看到的 SO_REUSEPORT 的目的
  • connect 的手册页说连接的 UDP 套接字应该只从它所连接的地址接收数据报。这不是我看到的行为。请注意,此代码在 Windows 上运行良好。
  • 这来自手册页:“对于 UDP 套接字,与让多个进程竞争的传统技术相比,使用此选项可以更好地将传入数据报分配给多个进程(或线程)在同一个套接字上接收数据报。”它在 Windows 上工作的事实可能只是你对数据结构排序很幸运,即它不是你应该依赖的东西。
  • 是的,但事实如何(再次引用连接手册页): “如果套接字 sockfd 是 SOCK_DGRAM 类型,那么 addr 是默认发送数据报的地址, 以及接收数据报的唯一地址。” 你是说连接手册页有误吗?您链接的所有信息都没有表明这一点。
猜你喜欢
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 2014-01-04
  • 1970-01-01
  • 1970-01-01
  • 2011-12-05
  • 2021-07-03
  • 1970-01-01
相关资源
最近更新 更多