我正在使用GCDAsyncUdpSocket打开UDP套接字,然后将其绑定到端口。该类只是常见的POSIX套接字调用的包装,如socket
,bind
等。
情景1:
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端口在shell上的样子。如果我想再次使用该端口号,我似乎必须重启我的机器: - (
不,我没有旧的进程阻止端口阻塞。我使用ps aux
和lsof -i | grep UDP
进行了检查。
情景2:
如果从未使用该端口,系统不关心我是否不能很好地关闭它。这应该是这样的。
我的问题:
这里有什么问题?当然,在完美的世界中,程序不会崩溃,并且套接字都会被POSIX close
函数关闭。在一个不完美的世界里,我只需键入Cmd-。在XCode中杀死我正在开发的应用程序,并且不调用close
。
当我尝试将我的套接字绑定到UDP端口时,我真正想对操作系统说的是:“请OSX 10.8.5,将我的套接字绑定到端口23141.如果其他程序打开它目前正在监听,那么你可能会告诉我端口正在使用,但如果没有正在运行的程序关心这个端口,那么让我把它绑定到端口23141 !!“这是OSX的错误吗?这是新的吗?它是一个记录在案的已知错误,还是所谓的“功能”?
答案 0 :(得分:2)
这似乎是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 ......(听起来像个笑话,不是吗?)