cocoa-touch - 即使断开连接,GCDAsyncSocket 也无法多次接受 OnPort

标签 cocoa-touch sockets gcdasyncsocket

我希望能够关闭当前监听端口的套接字,然后返回到它并重新建立对该端口的监听。我无法这样做,因为在另一个服务器监听套接字上的第二个 acceptOnPort 调用总是以错误结束(地址已在使用中)。如何关闭监听套接字并重新建立一个新的?

最佳答案

issue 146我刚刚添加的。

GCDAsyncSocket 永远不会解除分配,因为 dispatch_source_set_event_handler 持有对一个 block 的引用,该 block 持有对 GCDAsyncSocket 自身的引用。

这导致无法关闭然后重新打开 GCDAsyncSocket 监听器,因为该地址已在使用中。

这可以通过将引用更改为弱引用来解决。在 dispatch_source_set_event_handler 之前,添加以下行:

__weak GCDAsyncSocket* weakSelf = self;

然后用weakSelf代替self来调用doAccept。

while ([weakSelf doAccept:socketFD] && (++i < numPendingConnections));

您需要重复此操作两次,一次用于 ipv4,一次用于 ipv6。

此时,您会发现GCDAsyncSocket 永远不会被释放是一件好事,因为它会立即崩溃,因为dealloc 运行。这是因为 dealloc 调用 closeWithError,而后者又调用委托(delegate) socketDidDisconnect,将 GCDAsyncSocket self 作为参数传递。 ARC 会立即保留崩溃的 GCDAsyncSocket,因为 GCDAsyncSocket 当前正在被释放。

这可以通过将“delegate = nil”移动到 dealloc 的开头来解决,您也可以这样做,因为此时无法安全地调用委托(delegate)(好吧,如果您希望能够通过 GCDAsyncSocket,你不能再这样做了)。在这种情况下,另一种方法是调用 socketDidDisconnect:nil。

无论哪种方式,都意味着不会调用 socketDidDisconnect,或者不会使用适当的 GCDAsyncSocket 作为参数来调用,这可能会破坏 API 协定,但在这一点上是不可避免的。

更好的 API 是在 dealloc 发生之前调用某种“Kill”方法来终止 GCDAsyncSocket。

关于cocoa-touch - 即使断开连接,GCDAsyncSocket 也无法多次接受 OnPort,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15488298/

相关文章:

objective-c - GCDAsyncSocket 错误

ios - 如何使用 GCDAsyncUdpSocket 通过 wifi 和蓝牙进行多播

ios - NSCompoundPredicate 给我一个错误,指出它找不到 'init' 的重载。这在最新的 XCode 6.1 更新之前有效

c# - 如何避免 TCP 套接字在断开连接时抛出 SocketException?

iphone - iOS:监控电池电量使用更多电池?应该自动保存吗?

python - C TCP Echo Server - 数据仅在 close() 时显示

Android 持久套接字连接规则

iphone - GCDAsyncSocket - 读取流永远不会完成

objective-c - Objective-C : Retrieving contents of a folder from a server

Xcode 运行后 iPhone 模拟器崩溃