2016-01-29 51 views
2

我想在Linux上使用TCP 和標準的socket.h庫實現一個簡單的客戶端/服務器程序。服務器處理多個客戶端,每個客戶端可以隨時關閉()或關閉()套接字。TCP:recv()得到ECONNRESET

在服務器端

(使用非阻塞讀):

int nBytes; 
if ((nBytes = recv(socket, buffer, BUFFER_SIZE, MSG_DONTWAIT)) == -1) 
{ 
    if (errno != EAGAIN && errno != EWOULDBLOCK) 
    { 
     //print to log 
    } 

} 
if (nBytes == 0) 
{ 

    //other side closed the connection 
} 

我得到的recv()返回-1和錯誤設置爲ECONNRESET。如果客戶端已經關閉連接,不應該recv()返回0?

+0

tcpdump會告訴你實際發生的情況 – pm100

回答

6

有許多原因,包括但不限於:

  • 同行故意重置連接
  • 對方關閉了連接,同時他仍然有懸而未決
  • 你已經發送的數據未讀數據一個已經被對等關閉的連接
  • 您有待處理的寫入數據並且TCP重試已超時
  • TCP保持活動檢測到連接丟失。

這是一個致命錯誤,您應該在收到套接字時關閉套接字。

每個客戶端可以在任何時候想要close()shutdown()插槽。

不,他不能。往上看。

+0

我想知道爲什麼在recv中沒有提到這個致命的錯誤 – susdu

+2

@susdu這個錯誤情況在:如果出現以下情況,則recv()函數將失敗:... [ECONNRESET] 連接被對等方強制關閉。 –

+0

@susdu'協議層可能會生成額外的錯誤...' – EJP

3

如果客戶端沒有讀取發送的數據,他可能會收到ECONNRESET。如果他正確地關閉了連接,你會得到0.

+0

你會在這種情況下得到它,但也有其他的。 – EJP

4

如果遠程對等方乾淨地關閉了連接,並且在本地沒有更多字節等待讀取,那麼yes,recv()應該返回0。所以,如果你得到一個ECONNRESET,那麼有理由認爲有序關閉不是發生了什麼。

ECONNRESET通常表示遠程對等體發送了一個RST數據包,而沒有首先關閉連接。這可能發生的原因有很多。另外,正如EJP所觀察到的,重置也可能源自本地。

在任何情況下,一個ECONNRESET後,它不是合理的假設,你將能夠從插座還讀什麼,所以你的具體情況你應該處理它一樣一樣的,你處理recv()返回0方式,+/-記錄。

+1

重置可以源自您的末端以及對等體。 – EJP

+0

謝謝,@EJP;答案已更新。 –

+0

您應該將其作爲連接上的致命錯誤處理,與乾淨的斷開連接無異。 – EJP

相關問題