我希望能夠關閉當前偵聽端口的套接字,然後再回到端口並重新建立偵聽端口。我無法這樣做,因爲在另一個服務器偵聽套接字上的第二個acceptOnPort調用總是以錯誤結束(地址已被使用)。我怎樣才能關閉一個監聽套接字並重新建立一個新套接字呢?GCDAsyncSocket即使斷開連接後也不能多次接受端口
回答
請參閱我剛剛添加的issue 146。
GCDAsyncSocket不會釋放,因爲dispatch_source_set_event_handler持有對保存對GCDAsyncSocket self的引用的塊的引用。
由於地址已被使用,導致無法關閉然後重新打開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,後者又調用委託socketDidDisconnect,將GCDAsyncSocket self作爲參數傳遞。 ARC會立即保留當GCDAsyncSocket當前正在解除分配時崩潰的GCDAsyncSocket。
這可以通過將「delegate = nil」移動到dealloc的開頭來解決,您可以這樣做,因爲在那時無法安全地調用委託(如果您想要,這是不可能的能夠通過GCDAsyncSocket,你不能再這樣做)。另一種方法是在這種情況下調用socketDidDisconnect:nil。
無論哪種方式,這意味着socketDidDisconnect不會被調用,或者不會被調用適當的GCDAsyncSocket作爲參數,這可能會破壞API合約,但在這一點上是不可避免的。
更好的API應該是在發生dealloc之前有某種「Kill」方法調用來殺死GCDAsyncSocket。
- 1. KryoNet:連接後立即斷開連接
- 2. PHPWebsocket客戶端立即斷開連接
- 3. GCDASyncSocket SSL不連接
- 4. 即使連接被接受,「recv」也不起作用
- 5. 連接/斷開COM端口預計
- 6. 不能斷開BLE連接
- 7. Android BluetoothSocket連接後立即斷開連接
- 8. 用戶在chrooted SSH連接成功後立即斷開連接
- 9. 客戶端斷開連接
- 10. 對於使用PyBluez的藍牙連接,套接字連接即使在配對後也未被接受
- 11. socket.io斷開連接事件,客戶端斷開連接檢測
- 12. TcpListener停止接受或接受斷開的連接
- 13. TCP:當客戶端連接,發送數據和斷開連接之前接受
- 14. 斷開連接後重新連接到串口
- 15. 多路連接斷開連接
- 16. 多路連接隨機斷開連接
- 17. GCDAsyncSocket不開放口
- 18. 斷開連接後QuickFIX marketdatarequest
- 19. FtpWebRequest.GetRequestStream()斷開連接後
- 20. PASV後FTP斷開連接
- 21. C#客戶端/服務器套接字在斷開連接後將不會再次連接
- 22. Kryonet在多次發送自定義對象後斷開連接
- 23. SignalR在多次調用方法後斷開連接
- 24. 即使端口設置爲不正確,Django也會連接到mysql
- 25. Kryonet在客戶端2連接後立即斷開客戶端1
- 26. 嘗試使用斷開連接端口對象
- 27. 如何已斷開連接端口使用的Java
- 28. C STREAM客戶端套接字在斷開連接後重用
- 29. WebSocket立即斷開連接 - Openshift
- 30. 的Linux不接受連接到端口25
我對您的建議進行了__weak更改,並且在嘗試第二次接受OnPort時仍出現錯誤。我錯過了什麼? – Boon 2014-02-27 21:40:18
Peter,一旦我在隨後的acceptOnPort上引入了一點點延遲,你的建議就可以工作。謝謝! – Boon 2014-02-27 21:59:09