【问题标题】:How do I not destroy an UDP port when binding a socket?绑定套接字时如何不破坏 UDP 端口?
【发布时间】:2014-01-06 18:35:31
【问题描述】:

我正在使用GCDAsyncUdpSocket 打开一个 UDP 套接字,然后我将它绑定到一个端口。该类只是普通 POSIX 套接字调用(如 socket、bind 等)的包装器。

场景 1:

  • MyMacBook:启动进程 A
  • MyMacBook:打开 UDP 端口 23141 => 成功
  • SomeComputer:将 UDP 数据包发送到 MyMacBook,端口 23141
  • MyMacBook:标准 OSX 防火墙询问我是否要允许传入网络连接,我同意。
  • MyMacBook:忽略数据包,不要读取它。 (或者至少,我没有看到一条日志消息告诉我我收到了一个数据包。要么我的代码坏了,要么 CocoaAsyncSocket 代码坏了,要么操作系统没有向我的程序报告数据包。)
  • MyMacBook:杀死进程 A
  • MyMacBook:启动进程 A
  • MyMacBook:打开 UDP 端口 23141 => 失败:Error Domain=NSPOSIXErrorDomain Code=48 "Address already in use" UserInfo=0x100407f30 {NSLocalizedDescription=Address already in use, NSLocalizedFailureReason=Error in bind() function

为什么???

netstat -n |grep 2314
udp4     626      0  *.23146                *.*                               
udp4    1251      0  *.23141                *.*

^^这是外壳上损坏的 UDP 端口的样子。如果我想再次使用该端口号,我似乎必须重新启动我的机器:-(

不,我没有阻塞端口的旧进程。我检查了ps aux 和lsof -i | grep UDP。

场景 2:

  • MyMacBook:启动进程 A
  • MyMacBook:打开 UDP 端口 23143 => 成功
  • MyMacBook:杀死进程 A
  • MyMacBook:启动进程 A
  • MyMacBook:打开 UDP 端口 23143 => 成功
  • MyMacBook:杀死进程 A
  • MyMacBook:启动进程 A
  • MyMacBook:打开 UDP 端口 23143 => 成功
  • MyMacBook:杀死进程 A
  • ...

如果端口从未使用过,系统不会在意我是否关闭它。应该是这样的。

我的问题:

这里有什么问题?当然,在一个完美的世界中,程序不会崩溃,并且套接字都使用 POSIX close 函数关闭。在一个不完美的世界里,我只需要输入 Cmd-。在 XCode 中杀死我正在开发的应用程序,并且不会调用 close。

当我试图将我的套接字绑定到 UDP 端口时,我真正想对操作系统说的是:“请 OSX 10.8.5,将我的套接字绑定到端口 23141。如果其他程序打开了它当前并且正在监听,那么你可能会告诉我该端口正在使用中,但是如果没有正在运行的程序关心这个端口,那么让我将它绑定到端口 23141!!”这是一个 OSX 错误吗?这是新的吗?它是记录在案的已知错误,还是所谓的“功能”?

【问题讨论】:

  • lsof -i :23141 说什么?它应该显示正在使用该端口的进程。
  • 我的猜测是,在场景 1 中,您正在生成一个继承套接字的后台进程,并且当您杀死进程 A 时它不会被杀死。
  • 无输出,退出代码 1。lsof -i | grep UDP 没有列出我的端口号,也没有列出打开它的程序。 netstat -n | grep 23141 显示 udp4 1563 0 *.23141 *.* ,这对我来说似乎很愚蠢。 ps aux 没有列出我的应用程序。
  • @Barmar:我不产生任何进程,我不打电话给fork。我虽然使用 dispatch_queues。但我确信当我按下 Cmd- 时它们会被杀死。在 XCode 中。
  • 好像以前见过这样的:superuser.com/questions/504750/…那里也没有解决办法

标签: c macos sockets networking udp


【解决方案1】:

这似乎是 OSX 中的一个错误。

相关帖子:
https://superuser.com/questions/504750/kill-udp-port-that-has-no-process
https://apple.stackexchange.com/questions/71300/how-can-i-unbind-a-udp-port-that-has-no-entry-in-lsof
(@Barmar:感谢您找到这些文章)

1) 我已经注意到,如果 UDP 端口损坏(它已绑定,但未绑定到特定进程),那么您必须重新启动计算机才能再次使用该端口。注销,然后重新登录不起作用。

2) 我发现,如果您禁用 OSX 防火墙,没有问题。这意味着问题是标准 OSX 防火墙中的错误。但是,如果您禁用防火墙,损坏的端口不会完好无损,您仍然需要重新启动计算机才能破解它。但是:如果防火墙关闭,则不会有任何端口损坏。

我们可以从第 2 部分中学到一些东西:OSX 防火墙不是一个简单的数据包过滤器。它似乎在内核级别破解了套接字命令。

也许有人想写一份错误报告并将其发送给 Apple……(听起来像个笑话,不是吗?)

【讨论】:

    猜你喜欢
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-27
    • 2014-06-04
    • 2014-06-23
    相关资源
    最近更新 更多