2012-09-13 57 views
14

我有需要在一段時間內一些數據發送到服務器的應用程序。簡單的方法是關閉連接,然後在我想發送內容時再打開它。但我要保持連接打開,所以當我要發送數據時,我第一次使用此功能檢查連接:檢查套接字連接或不

bool is_connected(int sock) 
{ 
    unsigned char buf; 
    int err = recv(sock,&buf,1,MSG_PEEK); 
    return err == -1 ? false : true; 
} 

壞的部分是,這是行不通的。當沒有數據要接收時它會掛起。我能做什麼?我如何檢查連接是否仍然打開?

+3

http://stackoverflow.com/questions/4142012/how-to-find-the-socket-connection-state-in-c – BoBTFish

回答

17

不要先檢查,然後發送。這是浪費精力並且無論如何都無法工作 - 當您檢查和發送時,狀態可能會發生變化。只要做你想做的事情,並處理錯誤,如果它失敗。

要檢查狀態,請使用:

int error_code; 
int error_code_size = sizeof(error_code); 
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size); 
+1

確實...但有時候檢查一個套接字是否仍然連接是有用的。將其設置爲非阻塞,然後使用peek_msg進行讀取是引發錯誤代碼以檢查套接字是否仍處於連接狀態的好方法。 –

+2

@RafaelBaptista爲什麼? *使用*它會檢查。由於David上面給出的原因,測試首先不能可靠地工作。 – EJP

+0

@EJP:我想檢查客戶端連接是否存活,以免浪費資源。 – che

12

您需要啓用非阻塞的行爲,通過使用fcntl設置O_NONBLOCK。一個簡單但不規範的方式做非阻塞讀是使用:

recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT); 

之後,你必須如果失敗檢查errno。它可能會失敗,EAGAIN,或者它可能會失敗,EBADFENOTCONN


顯然,對付這將是避免「遺忘」如果套接字連接與否最簡單和乾淨的方式。如果套接字斷開連接一次recv返回0或send回報EPIPE你會發現。

+2

這不會檢測到所有連接失敗。只有send()可以做到這一點。 – EJP

+0

@EJP事實確實如此。我只是在改進操作的解決方案。你所建議的是唯一的防彈解決方案,但它需要發送。 – cnicutar

2

默認使用TCP不允許死套接字的非常及時檢測(正常關閉之外),所以我會認爲,像這樣的「is_connected」功能是對所有實際的目的主要是沒用的。考慮實施應用層保持活躍狀態​​,並根據及時響應(或缺乏響應)跟蹤它是否有效。

編輯:發佈後,我看到BoBTFish的鏈接,這實際上是一回事。