我有一個TCP連接。服務器只是從客戶端讀取數據。現在,如果連接丟失,客戶端在將數據寫入管道(斷開的管道)時會出錯,但服務器仍在該管道上偵聽。有沒有什麼方法可以找到連接是否UP?如何在C中找到套接字連接狀態?
回答
您能夠打電話的getsockopt就像如下:
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len);
要測試插座起來:
if (retval != 0) {
/* there was a problem getting the error code */
fprintf(stderr, "error getting socket error code: %s\n", strerror(retval));
return;
}
if (error != 0) {
/* socket has a non zero error status */
fprintf(stderr, "socket error: %s\n", strerror(error));
}
對於BSD套接字我會找Beej's guide。當recv返回0時,您知道另一端已斷開連接。
現在你可能會問,檢測另一側斷開的最簡單方法是什麼?做這件事的一種方法是讓一個線程總是進行recv。該線程將能夠立即分辨客戶端何時斷開連接。
不,它不會。如果(a)它從對方那裏收到一個這樣的數據包,或者(b)它超時等待發送的數據包的確認,tcp堆棧只能檢測到套接字已關閉。在recv的情況下,如果中間路由器發生故障或遠程主機異常關閉了套接字(不發送關閉),則不會有數據包到達,從而通知套接字堆棧recv正在等待關閉連接。 – 2010-11-10 08:03:32
TCP存活套接字選項(SO_KEEPALIVE)將有助於在這種情況下關閉服務器套接字以防連接丟失。
它不會關閉任何東西。它會在下次發送或接收時發生錯誤,但套接字保持打開狀態。 – EJP 2015-12-20 06:34:37
可靠地檢測套接字是否仍連接的唯一方法是定期嘗試發送數據。定義客戶端忽略的應用程序級別「ping」數據包通常更方便,但如果協議已經被指定出來而沒有這種功能,則應該可以通過設置SO_KEEPALIVE套接字選項來配置tcp套接字來完成此操作。我鏈接到了winsock文檔,但是所有類似BSD的套接字棧都應該具有相同的功能。
感謝您的時間。我考慮過SO_KEEPALIVE選項,但在Linux中激活KeepAlive探針的默認時間是2小時。如果我將其降低到幾秒鐘,其他應用程序可能會受到影響。我會給它一個反正:) – Blacklabel 2010-11-10 08:44:37
這就是爲什麼它通常訴諸應用程序級ping數據包,服務器可以發送每當連接已安靜一段時間。如果 - 就像在http中一樣 - 你不能在沒有收到客戶端請求的情況下發送數據,那麼你別無選擇,只能簡單地關閉已經保持「太長時間」的連接,並在需要時依賴客戶端重新連接。 – 2010-11-10 09:41:48
@Blacklabel Linux(和其他)允許您設置每個套接字的存活超時時間,請參閱'man 7 tcp' – nos 2010-11-10 20:12:22
我有類似的問題。我想知道服務器是連接到客戶端還是客戶端連接到服務器。在這種情況下,recv函數的返回值可以派上用場。如果套接字未連接,它將返回0字節。因此,使用這個我打破了循環,不必使用任何額外的函數線程。如果專家認爲這是正確的方法,您也可以使用相同的方法。
get sock opt可能有些用處,但是,另一種方法是爲SIGPIPE安裝信號處理程序。基本上,無論套接字連接何時中斷,內核都會向進程發送一個SIGPIPE信號,然後您可以執行必要的操作。但是這仍然不能提供知道連接狀態的解決方案。希望這可以幫助。
您應該嘗試使用:getpeername函數。
現在,當連接斷開時,您將收到errno: ENOTCONN - 套接字未連接。 這意味着你的羽絨服。
else(如果沒有其他故障)那裏的返回碼將會是0 - >這意味着UP。
資源: 手冊頁:http://man7.org/linux/man-pages/man2/getpeername.2.html
Nope中的TCP_KEEPIDLE套接字選項。 ENOTCONN表示在傳遞給getpeername函數的套接字上沒有調用connect函數。套接字可能會「連接」,但這並不意味着連接已啓動。 – 2015-12-17 18:17:13
你好,你看過一個TCP連接但它沒有連接嗎? – 2015-12-26 21:06:59
「連接」我的意思是一個套接字,其中connect已成功調用。說「起來」,我的意思是連接不是半開放的。當服務器僅作爲監聽者時,它可以永久地在連接的套接字上永久地進行監聽,該套接字並非實際上(即半開)。本文詳細解釋了半開連接:http://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html – 2015-12-26 21:17:16
可以使用SS_ISCONNECTED
宏getsockopt()
功能。 SS_ISCONNECTED
在socketvar.h
中定義。
看起來像內核內核對我來說。 – EJP 2015-12-20 06:39:39
有一個簡單的方法來通過調用poll
來檢查套接字連接狀態。首先,您需要輪詢套接字,是否有POLLIN
事件。
- 如果套接字未關閉並且有數據要讀取,那麼
read
將返回大於零。 - 如果插座上沒有新的數據,然後
POLLIN
將在revents
- 如果關閉套接字然後
POLLIN
標誌將被設置爲一個讀將返回0
這裏是設置爲0一小段代碼:
int client_socket_1, client_socket_2;
if ((client_socket_1 = accept(listen_socket, NULL, NULL)) < 0)
{
perror("Unable to accept s1");
abort();
}
if ((client_socket_2 = accept(listen_socket, NULL, NULL)) < 0)
{
perror("Unable to accept s2");
abort();
}
pollfd pfd[]={{client_socket_1,POLLIN,0},{client_socket_2,POLLIN,0}};
char sock_buf[1024];
while (true)
{
poll(pfd,2,5);
if (pfd[0].revents & POLLIN)
{
int sock_readden = read(client_socket_1, sock_buf, sizeof(sock_buf));
if (sock_readden == 0)
break;
if (sock_readden > 0)
write(client_socket_2, sock_buf, sock_readden);
}
if (pfd[1].revents & POLLIN)
{
int sock_readden = read(client_socket_2, sock_buf, sizeof(sock_buf));
if (sock_readden == 0)
break;
if (sock_readden > 0)
write(client_socket_1, sock_buf, sock_readden);
}
}
這是一個好的開始,但是OP所要求的是關於錯誤......如果套接字產生錯誤,你會得到一個'POLLERR','POLLHUP','POLLRDHUP'或'POLLNVAL'。如果你的'revents'設置了這些標誌中的任何一個,那麼你就知道這個套接字現在已經斷開,你可以正確使用它。此外,除非套接字返回「POLLOUT」,否則不應該寫入()。最後,至少在Linux下,它是'POLLIN'(否'_')。在https://github.com/m2osw/snapcpp/blob/master/snapwebsites/libsnapwebsites/src/snap_communicator.cpp找到圍繞7000行的完整功能版本 – 2017-01-23 05:52:13
- 1. 確定套接字連接狀態 - android
- 2. 如何確定客戶端套接字的連接狀態?
- 3. c#套接字連接
- 4. C#-PHP套接字連接
- 5. C#套接字雙連接?
- 6. HTML5 WebSocket連接到C#TCP套接字
- 7. 如何查找vxworks中套接字描述符的狀態
- 8. 如何連接到rild套接字
- 9. 如何連接到C#中的套接字像PuTTY?
- 10. 確定異步服務器中的套接字連接狀態
- 11. 如何關閉在C#中的TCP套接字連接
- 12. CF 3.5 C中的套接字連接#
- 13. boost asio有狀態套接字接口
- 14. 在C#中檢測網絡狀態(連接 - 斷開連接)
- 15. 如何將代理支持添加到C#套接字連接?
- 16. 如何將套接字連接到調制解調器連接?
- 17. 將C套接字客戶端連接到C#套接字服務器
- 18. 頁面刷新後保存TCP套接字(連接)的狀態
- 19. 使用套接字連接獲取網站的狀態代碼
- 20. 連接之前的Android檢查套接字狀態
- 21. Java套接字到C套接字
- 22. C++套接字-WString到Java套接字
- 23. BlueSocket在連接到Python套接字套接字時拒絕連接
- 24. 當另一個套接字不再可用時,C#套接字保持連接狀態
- 25. 如何在C#中進行非阻塞套接字調用以確定連接狀態?
- 26. 連接到Docker中的mongoDB套接字
- 27. 如何使用boost :: asio使套接字連接保持活動狀態?
- 28. 中斷連接套接字
- 29. Python套接字 - 連接套接字
- 30. C#:套接字問題 - 幾秒鐘後連接的套接字斷開連接
我想你應該澄清無論您是爲Windows或Linux開發/ UNIX .. – nairdaen 2010-11-10 07:14:21
在出現錯誤發送的結果,你應該首先檢查什麼樣的錯誤,它實際上是,然後決定是一個可恢復的錯誤(它可以修復它自己嗎?)或者如果它意味着你的連接肯定死了。如果確實死了,關閉插座。如果仍然可以通過任何流量,另一側將看到套接字已關閉。如果你無法通過任何交通,你仍然失去。在這種情況下,另一方可以注意到的唯一方法是發送一些本應該引發答覆的東西,如果沒有這樣的答覆,那麼另一方已經死亡。 – Mecki 2017-07-18 15:57:47