2014-01-08 70 views
0

我寫了簡單的TCP/IP多線程ANSI C服務器(客戶端是C sharp),一切正常,除非服務器沒有從客戶端接收到合適的信號時它不會結束線程並且關閉它的套接字(例如,當客戶端崩潰時)。如果這些線程累積起來,最終可能會出現問題。
我有存儲在鏈接列表中的線程 - 遍歷它們不是問題。然而,默認情況下,它們都被recv()阻塞,並且因爲死的客戶端不會發送任何它們卡在內存中的東西。ANSI C TCP/IP服務器在線客戶端列表

維護在線客戶列表的正確方法是什麼? (或者如何檢測連接斷開的線程)。

struct tListItem { 
pthread_t thisThread; 
char* name; 
int c_sockfd; 
int run; 
tListItem* next; 
tListItem* prev;}; 

struct tList{ 
tListItem* head; 
int count;}; 

碼螺紋:

while(param->run) 
{ 
    bzero(&buf, sizeof(buf)); 
    if ((readLen = recv(param->c_sockfd, buf, BUFFSIZE, 0)) == -1) 
    { 
     perror("Read error"); 
     param->run = 0; 
    } 
    else if (readLen > 0) { 
     printf("%s: %s \n", param->name, buf); 

     parseIncoming(param->c_sockfd, param, buf);}} 

,這裏是我的嘗試檢測連接中斷,但是這將導致服務器終止與無消息:

void* maintenance() { 
tListItem *item; 
char buf[4] = "PNG"; 
while(1) 
{ 
    usleep(2000000); 
     item= threadList->head; 
     while(item != 0) 
     { 
      if ((send(item->c_sockfd, buf, 3, NULL)) == -1) 
      { 
       perror("Write error"); 
       item->run = 0; 
      } 
      item = item->next; 
     } 
} 

}

+0

我建議發佈一些實際的代碼。我想,這將有助於更好的反應。 –

回答

0

有幾種常見的處理辦法:

  1. 在TCP協議上實現心跳/乒乓功能。也就是說,客戶端和/或服務器週期性地向另一端發送心跳消息。如果服務器在一段時間內沒有收到任何數據或心跳消息,例如心跳週期的兩倍,或者如果從服務器發送心跳消息失敗,則認爲連接已經死機並關閉它。

  2. 執行整體數據超時。每次服務器接收到數據時,都會讀取當前時間。定期檢查上次接收數據時的連接情況,以及暫時未收到數據的超時/關閉連接情況。

  3. 啓用TCP保持活動。如果你不能做1或2,這基本上是最後的手段。它會幫助你檢測死去的同伴,因爲如果同伴不能到達,TCP keepalive會斷開連接。 (雖然它不會幫助您檢測閒置客戶端)。請注意,Keepalive的默認值爲小時數。

在你應該總是要讀所有的情況下()/的recv()或以其他方式監控讀取事件插座這樣你可以學到儘可能快,如果連接積極打破。

如果您正在阻止read()/ recv()調用,實現此功能也很困難,您通常需要在read()上設置一個超時值,以便可以定期喚醒併發送心跳消息或者檢查客戶端是否已經閒置太久 - 這最好通過使用select()/ poll()或類似方法來完成,這樣您可以獲得超時而不是執行可能永遠不會返回的block read()。