【问题标题】:UDP socket still bound to previous port – how to reuse it?UDP 套接字仍然绑定到以前的端口——如何重用它?
【发布时间】:2022-01-16 21:12:25
【问题描述】:

我有一个音频流应用程序,它使用绑定到端口 50050 的 boost UDP 套接字。当应用程序在流式传输时关闭时,我目前遇到问题。重新启动应用程序时,它无法再绑定到端口 50050。 我做了一个“netstat -p UDP”,它显示了以下内容

Proto Recv-Q Send-Q 本地地址 外部地址(状态)

udp4 1026 0 *.50050 .

所以,基本上这个socket的接收队列不是空的,之前绑定的端口确实还是活跃的。

现在我想知道 a) 是否有办法强制绑定到端口 50050 或 b) 可以清除套接字接收队列或 c) 可以重用现有套接字或 d) 如果您有其他解决问题的建议?

提前致谢, 最好的

亚历克斯

【问题讨论】:

    标签: sockets boost udp port


    【解决方案1】:

    与 TCP 不同,一旦应用程序关闭了套接字,UDP 套接字就不会停留在某个临时状态。因此,您所看到的意味着仍然有一个进程拥有一个绑定到该端口的套接字。这表明应用程序没有完全关闭,但至少有一个线程仍在运行。或者它可能是继承了套接字的分叉子节点。

    虽然您可以使用 SO_REUSEADDR 创建一个额外的套接字(有关详细信息,请参阅其他 cmets 和答案),但这不会使现有的套接字处于非活动状态。发送到此端口的数据将仅在现有套接字之一结束,并且不会传播到所有套接字。这可能会导致数据丢失。

    【讨论】:

    • 这确实是我的想法,但是,现在没有这样的进程运行了。我通过 ps aux 和 top 检查了它,但没有发现任何“剩菜”。有什么我可能会错过的吗?
    • @AlexanderCarôt:不确定您使用的是哪个平台,但在 Linux 中您可以通过netstat -p -u 查找套接字的进程。
    • 我正在为 Linux、OSX 和 Windows 进行部署,但是,我在 OSX 上发现了 netstat 无法显示 PID 的问题。在那里我使用了 lsof -i -n -P | grep 50050 最终完成了这项工作 - 导致下一条消息。
    • 除了纯音频流之外,出于统计原因,我还执行了跟踪路由。调用由我的 C++ 应用程序通过 fp = popen(exec.c_str(), "r");其中 exec 包含基于控制台的 traceroute 调用,并且在主应用程序关闭后此调用仍在运行。非常感谢您的帮助 - 现在由我来解决这个问题!
    • 为了完整起见:我现在使用以下参数运行 traceroute:traceroute -I -w 1 -m 15 所以它使用 ICMP 而不是 UDP(拒绝连接较少),设置 1 s 而不是3 秒超时并将最大跳数限制为 15 而不是 20。
    【解决方案2】:

    在调用 bind 之前在套接字上设置 SO_REUSEADDR 属性。

    int fAllow = 1;
    int result;
    
    
    result = ::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &fAllow, sizeof(fAllow));
    

    【讨论】:

    • 虽然这在技术上是正确的,但它并不能解决仍然有一个套接字绑定到同一个端口的问题。发送到此端口的任何数据都将仅在其中一个套接字上结束,而不是同时在这两个套接字上结束。
    • @SteffenUllrich - 我同意 - 假设持有套接字的流氓进程仍在调用 recvrom 或等效的读取操作。 OP 需要找出仍然持有他的套接字的进程。他没有说是哪个操作系统,但有netstat 的命令行选项可以显示占用端口/套接字的进程。
    • 见上文——最终我可以弄清楚问题出在哪里,而且确实还有一个辅助进程正在运行,这是主要原因。但是,您的回答仍然有用,因为我明确询问了如何重用端口。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-04
    • 2014-02-06
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 2012-04-11
    相关资源
    最近更新 更多