簡體   English   中英

ANSI C TCP / IP服務器聯機客戶端列表

[英]ANSI C TCP/IP server online client list

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

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

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;
        }
}

}

有幾種常見的處理方法:

  1. 在TCP之上的協議中實現心跳/乒乓球。 即,客戶端和/或服務器定期向另一端發送心跳消息。 如果服務器在一段時間內(例如兩次心跳周期)未收到任何數據或心跳消息,或者如果從服務器發送心跳消息失敗,則認為連接已斷開並關閉連接。

  2. 實施整體數據超時。 每次服務器接收數據時,您都會讀取當前時間。 定期檢查連接的上次接收數據時間,並超時/關閉一段時間未接收數據的連接。

  3. 啟用TCP keepalive。 如果您無法執行1.或2,這基本上是不得已的方法。它將幫助您檢測死對等體,因為如果無法訪問對等體,則TCP keepalive將斷開連接。 (盡管這不會幫助您檢測閑置的客戶端)。 請注意,keepalive的默認值以小時為單位。

在所有情況下,都應始終執行read()/ recv()或以其他方式監視套接字的讀取事件,以便在連接中斷時盡快學習。

如果您要阻塞read()/ recv()調用,則也很難實現,通常需要在read()上設置超時,以便可以定期喚醒並發送心跳消息或檢查是否客戶端空閑時間過長-最好使用select()/ poll()之類的方法來完成,這樣您就可以獲得超時,而不是執行可能永遠不會返回的塊read()。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM