如何绑定到任何可用的端口?

Soo*_*nts 45 sockets networking

我需要一个应用程序,它将UDP数据包发送到某个网络服务器并接收响应.服务器回复请求来自的相同端口号,因此我首先需要将我的套接字绑定到任何UDP端口号.

对UDP端口号进行硬编码是一个坏主意,因为它可能被运行在同一台PC上的任何其他应用程序使用.

有没有办法将UDP套接字绑定到任何可用的端口?IMO应该是快速获得自由端口#的有效方法,它由例如accept()函数使用.

如果不是,那么尝试绑定并检查WSAEADDRINUSE/EADDRINUSE状态的最佳策略是什么:从1025或1025 + rand()或其他一些顺序尝试端口?

Rem*_*eau 212

另一种选择是将端口0指定为bind().这将允许您绑定到特定的IP地址(如果您已安装多个),同时仍然绑定到随机端口.如果您需要知道选择了哪个端口,则可以getsockname()在执行绑定后使用.

  • 绑定到端口0是绑定到OS分配的随机端口的官方文档方式. (26认同)
  • 它位于[`bind()`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms737550.aspx)文档中:"如果端口指定为零,则服务提供者从动态客户端端口范围为应用程序分配一个唯一的端口.在Windows Vista及更高版本中,动态客户端端口范围是介于49152和65535之间的值.这是从Windows Server 2003及更早版本的更改,其中动态客户端端口范围是1025和5000之间的值...应用程序可以在调用bind之后使用getsockname来学习已分配给套接字的地址和端口." (10认同)
  • 在linux内核中,端口#= 0作为随机分配请求的处理被认为是如此平凡,以至于它甚至没有给出规范的引用.(net/ipv4/inet_connection_sock.c,inet_csk_get_port). (6认同)
  • @alastair:这个问题被标记为`Windows`和`WinSock`,这就是我引用Microsoft文档的原因.绑定到端口0的AFAIK记录在4.2BSD标准中,平台实现基于. (5认同)
  • @EJP我并不反对这是有效的,只是指出除了(AFAICT)在Windows和Solaris上之外没有记录的行为. (3认同)
  • @hanshenrik Linux 确实记录了请求端口 0 时绑定到临时端口的行为。此行为在 https://man7.org/linux/man-pages/man7/ip.7.html 中进行了描述。另请参阅 https://man7.org/linux/man-pages/man2/bind.2.html 中“EADDRINUSE”的描述 (3认同)
  • @RemyLebeau 据我所知,这在 Linux、FreeBSD 或 Mac OS X 上 * 没有 * 记录(您上面引用的文档来自 Microsoft Windows,这几乎不是 BSD 网络文档的规范来源)。然而,它似乎确实有效。 (2认同)

ava*_*kar 35

sendto没有bind先调用的情况下调用,套接字将自动绑定(到一个空闲端口).

  • @claf你有点不合逻辑.由于topicstarter(绝对是另一个人)的选择,你贬低了某人的答案.我同意雷米的答案更好,而且他获得了应得的选票,但仅仅因为另一个更好的是胡说八道.⁺¹给不公平的downvote答案. (11认同)
  • Downvoting只是因为正确的答案应该是@Remy的一个(在bind中使用端口0). (8认同)
  • @claf隐式绑定也绑定,不是吗?在我看来,这两个答案都很有用. (5认同)