日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > > liwen01

liwen01_2020.01.10

  • 前言

  • (一)通過錯(cuò)誤碼和信號(hào)判斷

    • (1)寫數(shù)據(jù)信號(hào)和錯(cuò)誤碼判斷

    • (2)讀數(shù)據(jù)判斷返回值

  • (二)通過select系統(tǒng)函數(shù)判斷

  • (三)通過TCP_INFO套接字選項(xiàng)判斷

  • (四)通過SO_KEEPALIVE套接字選項(xiàng)判斷

  • (五)通過SO_RCVTIMEO/SO_SNDTIMEO判斷

  • (六)自定義通信心跳判斷

前言

在TCP網(wǎng)絡(luò)編程模型中,無論是客戶端還是服務(wù)端,在網(wǎng)絡(luò)編程的過程中都需要判斷連接的對方網(wǎng)絡(luò)狀態(tài)是否正常。在linux系統(tǒng)中,有很多種方式可以判斷連接的對方網(wǎng)絡(luò)是否已經(jīng)斷開。

  • 通過錯(cuò)誤碼和信號(hào)判斷
  • 通過select系統(tǒng)函數(shù)判斷
  • 通過TCP_INFO套接字選項(xiàng)判斷
  • 通過SO_KEEPALIVE套接字選項(xiàng)判斷
  • 通過SO_RCVTIMEO/SO_SNDTIMEO判斷

(一)通過錯(cuò)誤碼和信號(hào)判斷

(1)寫數(shù)據(jù)信號(hào)和錯(cuò)誤碼判斷

在寫TCP連接數(shù)據(jù)的時(shí)候,如果對方連接已經(jīng)正常斷開,那么寫數(shù)據(jù)端將會(huì)收到一個(gè)SIGPIPE信號(hào),可以通過這個(gè)信號(hào)知道對方連接已經(jīng)斷開。該信號(hào)信號(hào)會(huì)終止當(dāng)前進(jìn)程,如果不在對方連接斷開不退出進(jìn)程,那么就應(yīng)該注冊信號(hào)函數(shù)。

同時(shí),如果對方連接已經(jīng)正常斷開,那么write寫數(shù)據(jù)端將會(huì)返回寫錯(cuò)誤。返回的寫長度為-1,此時(shí)的錯(cuò)誤碼為:32,對應(yīng)錯(cuò)誤值為EPIPE;因此可以寫數(shù)據(jù)時(shí)write的返回值和錯(cuò)誤碼來判斷對方連接是否已經(jīng)斷開了。

(2)讀數(shù)據(jù)判斷返回值

如果當(dāng)前是默認(rèn)的阻塞模式讀取,那么此時(shí)read讀取返回的長度為0,錯(cuò)誤碼也是為0,其實(shí)表示讀取成功。這里需要注意read 和recv接口的默認(rèn)返回值是不一樣的,使用recv接口也會(huì)返回EPIPE錯(cuò)誤碼。client_tcp.c

/************************************************************
*Copyright (C),lcb0281at163.com lcb0281atgmail.com
*FileName: 01_client_tcp.c
*BlogAddr: caibiao-lee.blog.csdn.net
*Description: TCP 客戶端收發(fā)數(shù)據(jù) 
*Date:     2020-01-04
*Author:   Caibiao Lee
*Version:  V1.0
*Others:
 通過read write 函數(shù)的返回值和錯(cuò)誤碼判斷對方連接是否已經(jīng)斷開
*History:
***********************************************************/ #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #define SERVER_IP_ADDR "192.168.1.111" #define PORT 8888 /* 偵聽端口地址 */ void sig_proccess(int signo) { printf("Catch a exit signal\n"); exit(0); 
} void sig_pipe(int sign) { printf("Catch a SIGPIPE signal\n"); /* 釋放資源 */ } void process_conn_client(int s32SocketFd) { int size = 0; char buffer[1024] = {0}; char *sendData = "I am client"; for(;;)
 {
 size = write(s32SocketFd, sendData, strlen(sendData)+1); if(size!=strlen(sendData)+1)
 { printf("write data error size=%d errno=%d \n",size,errno); //return ; }
 
 size = read(s32SocketFd, buffer, 1024); if(size<=0)
 { printf("read data error size=%d errno=%d \n",size,errno); //return ;  }else { printf("recv Data: %s\n",buffer);
 }
 sleep(1);

 } 
} int main(int argc, char *argv[]) { struct sockaddr_in server_addr; int l_s32SocketFd = 0;

 
 signal(SIGINT, sig_proccess);
 signal(SIGPIPE, sig_pipe); /* 建立一個(gè)流式套接字 */ l_s32SocketFd = socket(AF_INET, SOCK_STREAM, 0); if(l_s32SocketFd < 0)
 {/* 出錯(cuò) */ printf("socket error\n"); return -1; 
 } /* 設(shè)置服務(wù)器地址 */ bzero(&server_addr, sizeof(server_addr)); /* 清0 */ server_addr.sin_family = AF_INET; /* 協(xié)議族 */ server_addr.sin_addr.s_addr = inet_addr(SERVER_IP_ADDR);/*服務(wù)器IP地址*//* 本地地址 */ server_addr.sin_port = htons(PORT); /* 服務(wù)器端口 */ /* 連接服務(wù)器 */ connect(l_s32SocketFd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
 process_conn_client(l_s32SocketFd); /* 客戶端處理過程 */ close(l_s32SocketFd); /* 關(guān)閉連接 */ return 0;
}

server_tcp.c

/************************************************************
*Copyright (C),lcb0281at163.com lcb0281atgmail.com
*FileName: 01_server_tcp.c
*BlogAddr: caibiao-lee.blog.csdn.net
*Description: TCP 客戶端收發(fā)數(shù)據(jù) 
*Date:     2020-01-04
*Author:   Caibiao Lee
*Version:  V1.0
*Others:
 通過read write 函數(shù)的返回值和錯(cuò)誤碼判斷對方連接是否已經(jīng)斷開
*History:
***********************************************************/ #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #define SERVER_IP_ADDR "192.168.1.111" #define PORT 8888 /* 偵聽端口地址 */ #define BACKLOG 2 /* 偵聽隊(duì)列長度 */ void sig_proccess(int signo) { printf("Catch a exit signal\n"); exit(0); 
} void sig_pipe(int sign) { printf("Catch a SIGPIPE signal\n"); /* 釋放資源 */ } /* 服務(wù)器對客戶端的處理 */ void process_conn_server(int s32SocketFd) { int size = 0; char buffer[1024]; /* 數(shù)據(jù)的緩沖區(qū) */ for(;;)
 { /* 從套接字中讀取數(shù)據(jù)放到緩沖區(qū)buffer中 */ size = read(s32SocketFd, buffer, 1024); if(size==0)
 {/* 沒有數(shù)據(jù) */ printf("read size = %d, error %d \n",size,errno); //return;  }else if(size<0)
 { printf("read size = %d, error %d \n",size,errno); //return ; }else { printf("recv data:%s \n",buffer);
 
 } memset(buffer,0,sizeof(buffer)); /* 構(gòu)建響應(yīng)字符,為接收到客戶端字節(jié)的數(shù)量 */ strcpy(buffer,"I am server");
 size = write(s32SocketFd, buffer, strlen(buffer)+1);/* 發(fā)給客戶端 */ if((strlen(buffer)+1)==size)
 {

 }else { printf("write data error size = %d, errno=%d\n",size,errno); //return ; }
 sleep(1);
 } 
} int main(int argc, char *argv[]) { int l_s32ServerFd = -1; int l_s32ClientrFd = -1; struct sockaddr_in server_addr; /* 服務(wù)器地址結(jié)構(gòu) */ struct sockaddr_in client_addr; /* 客戶端地址結(jié)構(gòu) */ int l_s32Ret = 0; /* 返回值 */ pid_t pid; /* 分叉的進(jìn)行id */ signal(SIGINT, sig_proccess);
 signal(SIGPIPE, sig_pipe); /* 建立一個(gè)流式套接字 */ l_s32ServerFd = socket(AF_INET, SOCK_STREAM, 0); if(l_s32ServerFd < 0)
 {/* 出錯(cuò) */ printf("socket error\n"); return -1; 
 } /* 設(shè)置服務(wù)器地址 */ bzero(&server_addr, sizeof(server_addr)); /* 清0 */ server_addr.sin_family = AF_INET; /* 協(xié)議族 */ server_addr.sin_addr.s_addr = inet_addr(SERVER_IP_ADDR);/*服務(wù)器IP地址*/ server_addr.sin_port = htons(PORT); /* 服務(wù)器端口 */ /*設(shè)置IP地址可以重復(fù)綁定*/ int l_s32UseAddr = 1; if(setsockopt(l_s32ServerFd, SOL_SOCKET, SO_REUSEADDR, &l_s32UseAddr, sizeof(int)) < 0)
 { printf("%s %d\tsetsockopt error! Error code: %d,Error message: %s\n", 
 __FUNCTION__, __LINE__, errno, strerror(errno)); return -2;
 } /* 綁定地址結(jié)構(gòu)到套接字描述符 */ l_s32Ret = bind(l_s32ServerFd, (struct sockaddr*)&server_addr, sizeof(server_addr)); if(l_s32Ret < 0)
 {/* 出錯(cuò) */ printf("bind error\n"); return -1; 
 } /* 設(shè)置偵聽 */ l_s32Ret = listen(l_s32ServerFd, BACKLOG); if(l_s32Ret < 0)
 {/* 出錯(cuò) */ printf("listen error\n"); return -1; 
 } /* 主循環(huán)過程 */ for(;;)
 { int addrlen = sizeof(struct sockaddr); /* 接收客戶端連接 */ l_s32ClientrFd = accept(l_s32ServerFd, (struct sockaddr*)&client_addr, &addrlen); if(l_s32ClientrFd < 0)
 { /* 出錯(cuò) */ continue; /* 結(jié)束本次循環(huán) */ } /* 建立一個(gè)新的進(jìn)程處理到來的連接 */ pid = fork(); /* 分叉進(jìn)程 */ if( pid == 0 )
 { /* 子進(jìn)程中 */ close(l_s32ServerFd); /* 在子進(jìn)程中關(guān)閉服務(wù)器的偵聽 */ process_conn_server(l_s32ClientrFd);/* 處理連接 */ }else {
 close(l_s32ClientrFd); /* 在父進(jìn)程中關(guān)閉客戶端的連接 */ }
 }
}

(二)通過select系統(tǒng)函數(shù)判斷

select實(shí)際是IO復(fù)用的一個(gè)接口,它可以同時(shí)檢測多個(gè)連接是否有數(shù)據(jù)可讀寫操作,并且可以設(shè)置檢測的超時(shí)時(shí)間。 在點(diǎn)對點(diǎn)的連接中如果select超時(shí),它返回值為0;

  • 當(dāng)出現(xiàn)異常的時(shí)候,返回-1,如果對方斷開可能收到104的錯(cuò)誤碼,也就是ECONNRESET,表示連接被重置
  • 當(dāng)select返回1,表示正常,如果read此時(shí)返回的值為0,表示對方連接已經(jīng)斷開。
/******************************************************** 
Function:     process_conn_server 
Description: 服務(wù)器對客戶端的處理
Input:    s32SocketFd :服務(wù)端接收到客戶端連接的ID;
OutPut: none
Return: 0: success,none 0:error
Others: 通過select判斷客戶端的連接狀態(tài)
Author: Caibiao Lee
Date:    2020-01-04
*********************************************************/ void process_conn_server(int s32SocketFd) { int size = 0; int l_s32Ret = 0; char buffer[1024]; /* 數(shù)據(jù)的緩沖區(qū) */ fd_set l_stReadfd; struct timeval l_stTimeout={0}; for(;;)
 { 
 l_stTimeout.tv_sec=0;
 l_stTimeout.tv_usec=10000;
 FD_ZERO(&l_stReadfd);
 FD_SET(s32SocketFd ,&l_stReadfd);
 l_s32Ret = select(s32SocketFd+1, &l_stReadfd,NULL,NULL, &l_stTimeout); if (l_s32Ret<=0)
 { printf("select error l_s32Ret=%d errno=%d\n",l_s32Ret,errno);
 usleep(100000);
 } else if(FD_ISSET(s32SocketFd,&l_stReadfd))
 { printf("l_s32Ret = %d \n",l_s32Ret); /* 從套接字中讀取數(shù)據(jù)放到緩沖區(qū)buffer中 */ size = read(s32SocketFd, buffer, 1024); if(size==0)
 {/* 沒有數(shù)據(jù) */ printf("read size = %d, error %d \n",size,errno); //return;  }else if(size<0)
 { printf("read size = %d, error %d \n",size,errno); //return ; }else { printf("recv data:%s \n",buffer);
 }
 } memset(buffer,0,sizeof(buffer)); /* 構(gòu)建響應(yīng)字符,為接收到客戶端字節(jié)的數(shù)量 */ strcpy(buffer,"I am server");
 size = write(s32SocketFd, buffer, strlen(buffer)+1);/* 發(fā)給客戶端 */ if((strlen(buffer)+1)==size)
 {

 }else { printf("write data error size = %d, errno=%d\n",size,errno); //return ; }
 sleep(1);
 } 
}

(三)通過TCP_INFO套接字選項(xiàng)判斷

通過getsockopt函數(shù)可以獲取TCP連接的連接狀態(tài),當(dāng)狀態(tài)為ESTABLISHED的時(shí)候表示該連接正常。TCP的其它狀態(tài)還有:

  • CLOSED:表示初始狀態(tài)。對服務(wù)端和C客戶端雙方都一樣。
  • LISTEN:表示監(jiān)聽狀態(tài)。服務(wù)端調(diào)用了listen函數(shù),可以開始accept連接了。
  • SYN_SENT:表示客戶端已經(jīng)發(fā)送了SYN報(bào)文。當(dāng)客戶端調(diào)用connect函數(shù)發(fā)起連接時(shí),首先發(fā)SYN給服務(wù)端,然后自己進(jìn)入SYN_SENT狀態(tài),并等待服務(wù)端發(fā)送ACK+SYN。
  • SYN_RCVD:表示服務(wù)端收到客戶端發(fā)送SYN報(bào)文。服務(wù)端收到這個(gè)報(bào)文后,進(jìn)入SYN_RCVD狀態(tài),然后發(fā)送ACK+SYN給客戶端。
  • ESTABLISHED:表示連接已經(jīng)建立成功了。服務(wù)端發(fā)送完ACK+SYN后進(jìn)入該狀態(tài),客戶端收到ACK后也進(jìn)入該狀態(tài)。
  • FIN_WAIT_1:表示主動(dòng)關(guān)閉連接。無論哪方調(diào)用close函數(shù)發(fā)送FIN報(bào)文都會(huì)進(jìn)入這個(gè)這個(gè)狀態(tài)。
  • FIN_WAIT_2:表示被動(dòng)關(guān)閉方同意關(guān)閉連接。主動(dòng)關(guān)閉連接方收到被動(dòng)關(guān)閉方返回的ACK后,會(huì)進(jìn)入該狀態(tài)。
  • TIME_WAIT:表示收到對方的FIN報(bào)文并發(fā)送了ACK報(bào)文,就等2MSL后即可回到CLOSED狀態(tài)了。如果FIN_WAIT_1狀態(tài)下,收到對方同時(shí)帶FIN標(biāo)志和ACK標(biāo)志的報(bào)文時(shí),可以直接進(jìn)入TIME_WAIT狀態(tài),而無須經(jīng)過FIN_WAIT_2狀態(tài)。
  • CLOSING:表示雙方同時(shí)關(guān)閉連接。如果雙方幾乎同時(shí)調(diào)用close函數(shù),那么會(huì)出現(xiàn)雙方同時(shí)發(fā)送FIN報(bào)文的情況,此時(shí)就會(huì)出現(xiàn)CLOSING狀態(tài),表示雙方都在關(guān)閉連接。
  • CLOSE_WAIT:表示被動(dòng)關(guān)閉方等待關(guān)閉。當(dāng)收到對方調(diào)用close函數(shù)發(fā)送的FIN報(bào)文時(shí),回應(yīng)對方ACK報(bào)文,此時(shí)進(jìn)入CLOSE_WAIT狀態(tài)。
  • LAST_ACK:表示被動(dòng)關(guān)閉方發(fā)送FIN報(bào)文后,等待對方的ACK報(bào)文狀態(tài),當(dāng)收到ACK后進(jìn)入CLOSED狀態(tài)。 功能代碼如下:
/******************************************************** 
Function:     check_tcp_alive 
Description: 通過TCP_INFO查詢網(wǎng)絡(luò)狀態(tài)
Input:    s32SocketFd :服務(wù)端接收到客戶端連接的ID;
OutPut: none
Return: 0: success,none 0:error
Others: 
Author: Caibiao Lee
Date:    2020-01-04
*********************************************************/ int check_tcp_alive(int s32SocketFd) { while(1)
 { printf("alive  s32SocketFd = %d \n",s32SocketFd); if(s32SocketFd>0)
 { struct tcp_info info; int len = sizeof(info);

 getsockopt(s32SocketFd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len); printf("info.tcpi_state = %d\n",info.tcpi_state); if(info.tcpi_state == TCP_ESTABLISHED)
 { printf("connect ok \r\n"); //return 0; } else { printf("connect error\r\n"); //return -1; }
 }
 sleep(1); printf("\n\n");
 }
}

(四)通過SO_KEEPALIVE套接字選項(xiàng)判斷

選項(xiàng)SO_KEEPALIVE用于設(shè)置TCP連接的保持,當(dāng)設(shè)置此項(xiàng)后,連接會(huì)測試連接的狀態(tài)。這個(gè)選項(xiàng)用于可能長時(shí)間沒有數(shù)據(jù)交流的連接,通常在服務(wù)器端進(jìn)行設(shè)置。

當(dāng)設(shè)置SO_KEEPALIVE選項(xiàng)后,如果在兩個(gè)小時(shí)內(nèi)沒有數(shù)據(jù)通信時(shí),TCP會(huì)自動(dòng)發(fā)送一個(gè)活動(dòng)探測數(shù)據(jù)報(bào)文,對方必須對此進(jìn)行響應(yīng),通常有如下3種情況。

  1. TCP的連接正常,發(fā)送一個(gè)ACK響應(yīng),這個(gè)過程應(yīng)用層是不知道的。再過兩個(gè)小時(shí),又會(huì)再發(fā)送一個(gè)。
  2. 對方發(fā)送RST響應(yīng),對方在2個(gè)小時(shí)內(nèi)進(jìn)行了重啟或者崩潰。之前的連接己經(jīng)失效,套接字收到一個(gè)ECONNRESET錯(cuò)誤,之前的套接字關(guān)閉。
  3. 如果對方?jīng)]有任何響應(yīng),則本機(jī)會(huì)發(fā)送另外8個(gè)活動(dòng)探測報(bào)文,時(shí)間的間隔為75s,當(dāng)?shù)谝粋€(gè)活動(dòng)報(bào)文發(fā)送11分15秒后仍然沒有收到對方的任何響應(yīng),則放棄探測,套接字錯(cuò)誤類型設(shè)置為ETIMEOUT,并關(guān)閉套接字連接。如果收到一個(gè)ICMP控制報(bào)文響應(yīng),此時(shí)套接字也關(guān)閉,這種情況通常收到的是一個(gè)主機(jī)不可達(dá)的ICMP報(bào)文,此時(shí)套接字錯(cuò)誤類型設(shè)置為EHOSTUNREACH,并關(guān)閉套接字連接。SO_KEEPALIVE的使用場景主要是在可能發(fā)送長時(shí)間無數(shù)據(jù)響應(yīng)的TCP連接,例如Telnet會(huì)話,經(jīng)常會(huì)出現(xiàn)打開一個(gè)telnet客戶端后,長時(shí)間不用的情況,這需要服務(wù)器或 者客戶端有一個(gè)探測機(jī)制知道對方是否仍然活動(dòng)。根據(jù)探測結(jié)果服務(wù)器會(huì)釋放己經(jīng)失效的客戶端,保證服務(wù)器資源的有效性,例如有的telnet客戶端沒有按照正常步驟進(jìn)行關(guān)閉。

網(wǎng)上有不少資料介紹不推薦使用SO_KEEPALIVE來判斷網(wǎng)絡(luò)連接是否斷開,具體原因沒有去追蹤,這里不再介紹它的使用。

(五)通過SO_RCVTIMEO/SO_SNDTIMEO判斷

這個(gè)是通過套接字的SO_RCVTIMEO、SO_SNDTIMEO來設(shè)置收發(fā)數(shù)據(jù)超時(shí)。對于前面的前面的幾種判斷方式,都是基于對方正常網(wǎng)絡(luò)斷開后,主機(jī)才能夠正常的判斷到網(wǎng)絡(luò)狀態(tài)。如果連接的某一方突然斷電,主機(jī)并不能知道對方設(shè)備突然斷電,通過TCP_INFO查詢到的也是網(wǎng)絡(luò)正常,但實(shí)際情況是這是網(wǎng)絡(luò)連接已經(jīng)斷開了。

這時(shí),可以使用收發(fā)數(shù)據(jù)超時(shí)來判斷:     如果設(shè)置的時(shí)間沒有收到數(shù)據(jù),read時(shí)會(huì)返回-1,同時(shí)有錯(cuò)誤碼EAGAIN產(chǎn)生,這時(shí)是可以判斷出對連接已經(jīng)斷開了。     這種方式的確定就是,如果設(shè)定的一段時(shí)間沒有收發(fā)數(shù)據(jù),就會(huì)被判斷為超時(shí)斷開連接。

/******************************************************** 
Function:     process_conn_server 
Description: 通過設(shè)置收發(fā)操作判斷對方連接已經(jīng)斷開了
Input:    s32SocketFd :服務(wù)端接收到客戶端連接的ID;
OutPut: none
Return: 0: success,none 0:error
Others: 
Author: Caibiao Lee
Date:    2020-01-04
*********************************************************/ void process_conn_server(int s32SocketFd) { int size = 0; char buffer[1024]; /* 數(shù)據(jù)的緩沖區(qū) */ int optlen = -1; /* 整型的選項(xiàng)類型值 */ int l_s32Ret = 0; /* 設(shè)置發(fā)送和接收超時(shí)時(shí)間 */ struct timeval tv; tv.tv_sec = 10; /* 1秒 */ tv.tv_usec = 200000;/* 200ms */ optlen = sizeof(tv);
 l_s32Ret = setsockopt(s32SocketFd, SOL_SOCKET, SO_RCVTIMEO, &tv, optlen); /* 設(shè)置接收超時(shí)時(shí)間 */ if(l_s32Ret == -1){/* 設(shè)置接收超時(shí)時(shí)間失敗 */ printf("設(shè)置接收超時(shí)時(shí)間失敗\n"); 
 }
 
 l_s32Ret = setsockopt(s32SocketFd, SOL_SOCKET, SO_SNDTIMEO, &tv, optlen);/* 設(shè)置發(fā)送超時(shí)時(shí)間 */ if(l_s32Ret == -1){ printf("設(shè)置發(fā)送超時(shí)時(shí)間失敗\n"); 
 } for(;;)
 { /* 從套接字中讀取數(shù)據(jù)放到緩沖區(qū)buffer中 */ size = read(s32SocketFd, buffer, 1024); if(size==0)
 {/* 沒有數(shù)據(jù) */ printf("read size = %d, error %d \n",size,errno); //return;  }else if(size<0)
 { printf("read size = %d, error %d \n",size,errno); //return ; }else { printf("recv data:%s \n",buffer);
 
 } memset(buffer,0,sizeof(buffer)); /* 構(gòu)建響應(yīng)字符,為接收到客戶端字節(jié)的數(shù)量 */ strcpy(buffer,"I am server");
 size = write(s32SocketFd, buffer, strlen(buffer)+1);/* 發(fā)給客戶端 */ if((strlen(buffer)+1)==size)
 {

 }else { printf("write data error size = %d, errno=%d\n",size,errno); //return ; }
 sleep(1);
 } 
} 

(六)自定義通信心跳判斷

在一些比較重要的命令收發(fā)鏈接中,一般是客戶端和服務(wù)端會(huì)建立心跳機(jī)制,心跳時(shí)間間隔根據(jù)不同的業(yè)務(wù)需求而不同。當(dāng)約定的時(shí)間段內(nèi)沒有收到心跳數(shù)據(jù)包,就可以判斷對方是否已經(jīng)斷開了連接。

這種方式非常簡單,對于嵌入式設(shè)備而言,主要的缺點(diǎn)是心跳會(huì)耗費(fèi)流量,同時(shí)會(huì)增加一點(diǎn)點(diǎn)系統(tǒng)負(fù)載,并且不適合并發(fā)連接的情況。


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
關(guān)閉