監(jiān)理公司管理系統(tǒng) | 工程企業(yè)管理系統(tǒng) | OA系統(tǒng) | ERP系統(tǒng) | 造價咨詢管理系統(tǒng) | 工程設(shè)計管理系統(tǒng) | 甲方項目管理系統(tǒng) | 簽約案例 | 客戶案例 | 在線試用
X 關(guān)閉

TCP通信中服務(wù)器處理客戶端意外斷開的處理

申請免費試用、咨詢電話:400-8352-114

如果TCP連接被對方正常關(guān)閉,也就是說,對方是正確地調(diào)用了closesocket(s)或者shutdown(s)的話,那么上面的Recv或Send調(diào)用就能馬上返回,并且報錯。這是由于close socket(s)或者shutdown(s)有個正常的關(guān)閉過程,會告訴對方“TCP連接已經(jīng)關(guān)閉,你不需要再發(fā)送或者接受消息了”。

但是,如果意外斷開,客戶端(3g的移動設(shè)備)并沒有正常關(guān)閉socket。雙方并未按照協(xié)議上的四次揮手去斷開連接。

那么這時候正在執(zhí)行Recv或Send操作的一方就會因為沒有任何連接中斷的通知而一直等待下去,也就是會被長時間卡住。

像這種如果一方已經(jīng)關(guān)閉或異常終止連接,而另一方卻不知道,我們將這樣的TCP連接稱為半打 的。

解決意外中斷辦法都是利用?;顧C(jī)制。而保活機(jī)制分又可以讓底層實現(xiàn)也可自己實現(xiàn)。

1、 自己編寫心跳包程序

簡單的說也就是在自己的程序中加入一條線程,定時向?qū)Χ税l(fā)送數(shù)據(jù)包,查看是否有ACK,如果有則連接正常,沒有的話則連接斷開

2、 啟動TCP編程里的keepAlive機(jī)制

一)雙方擬定心跳(自實現(xiàn))

一般由客戶端發(fā)送心跳包,服務(wù)端并不回應(yīng)心跳,只是定時輪詢判斷一下與上次的時間間隔是否超時(超時時間自己設(shè)定)。服務(wù)器并不主動發(fā)送是不想增添服務(wù)器的通信量,減少壓力。

但這會出現(xiàn)三種情況:

情況1.

客戶端由于某種網(wǎng)絡(luò)延遲等原因很久后才發(fā)送心跳(它并沒有斷),這時服務(wù)器若利用自身設(shè)定的超時判斷其已經(jīng)斷開,而后去關(guān)閉socket。若客戶端有重連機(jī)制,則客戶端會重新連接。若不確定這種方式是否關(guān)閉了原本正常的客戶端,則在ShutDown的時候一定要選擇send,表示關(guān)閉發(fā)送通道,服務(wù)器還可以接收一下,萬一客戶端正在發(fā)送比較重要的數(shù)據(jù)呢,是不?

情況2.

客戶端很久沒傳心跳,確實是自身斷掉了。在其重啟之前,服務(wù)端已經(jīng)判斷出其超時,并主動close,則四次揮手成功交互。

情況3.

客戶端很久沒傳心跳,確實是自身斷掉了。在其重啟之前,服務(wù)端的輪詢還未判斷出其超時,在未主動close的時候該客戶端已經(jīng)重新連接。

這時候若客戶端斷開的時候發(fā)送了FIN包,則服務(wù)端將會處于CLOSE_WA上網(wǎng)行為狀態(tài);

這時候若客戶端斷開的時候未發(fā)送FIN包,則服務(wù)端處還是顯示ESTABLISHED狀態(tài);

而新連接上來的客戶端(也就是剛才斷掉的重新連上來了)在服務(wù)端肯定是ESTABLISHED;這時候就有個問題,若利用輪詢還未檢測出上條舊連接已經(jīng)超時(這很正常,timer總有個間隔吧),而在這時,客戶端又重復(fù)的上演情況3,那么服務(wù)端將會出現(xiàn)大量的假的ESTABLISHED連接和CLOSE_WA上網(wǎng)行為連接。

最終結(jié)果就是新的其他客戶端無法連接上來,但是利用netstat還是能看到一條連接已經(jīng)建立,并顯示ESTABLISHED,但始終無法進(jìn)入程序代碼。個人最初感覺導(dǎo)致這種情況是因為假的ESTABLISHED連接和 CLOSE_WA上網(wǎng)行為連接會占用較大的系統(tǒng)資源,程序無法再次創(chuàng)建連接(因為每次我發(fā)現(xiàn)這個問題的時候我只連了10個左右客戶端卻已經(jīng)有40多條無效連接)。而最近幾天測試卻發(fā)現(xiàn)有一次程序內(nèi)只連接了2,3個設(shè)備,但是有8條左右的虛連接,此時已經(jīng)連接不了新客戶端了。這時候我就覺得我想錯了,不可能這幾條連接就占用了大量連接把,如果說幾十條還有可能。但是能肯定的是,這個問題的產(chǎn)生絕對是設(shè)備在不停的重啟,而服務(wù)器這邊又是簡單的輪詢,并不能及時處理,暫時還未能解決。

二)利用KeepAlive

其實keepalive的原理就是TCP內(nèi)嵌的一個心跳包,

以服務(wù)器端為例,如果當(dāng)前 server 端檢測到超過一定時間(默認(rèn)是 7,200,000 milliseconds ,也就是 2 個小時)沒有數(shù)據(jù)傳輸,那么會向 client 端發(fā)送一個 keep-alive packet (該 keep-alive packet 就是 ACK和 當(dāng)前 TCP 序列號減一的組合),此時 client 端應(yīng)該為以下三種情況之一:

1. client 端仍然存在,網(wǎng)絡(luò)連接狀況良好。此時 client 端會返回一個 ACK 。server 端接收到 ACK 后重置計時器(復(fù)位存活定時器),在 2 小時后再發(fā)送探測。如果 2 小時內(nèi)連接上有數(shù)據(jù)傳輸,那么在該時間基礎(chǔ)上向后推延 2 個小時。

2. 客戶端異常關(guān)閉,或是網(wǎng)絡(luò)斷開。在這兩種情況下, client 端都不會響應(yīng)。服務(wù)器沒有收到對其發(fā)出探測的響應(yīng),并且在一定時間(系統(tǒng)默認(rèn)為 1000 ms )后重復(fù)發(fā)送 keep-alive packet ,并且重復(fù)發(fā)送一定次數(shù)( 2000 XP 2003 系統(tǒng)默認(rèn)為 5 次 , Vista 后的系統(tǒng)默認(rèn)為 10 次)。

3. 客戶端曾經(jīng)崩潰,但已經(jīng)重啟。這種情況下,服務(wù)器將會收到對其存活探測的響應(yīng),但該響應(yīng)是一個復(fù)位,從而引起服務(wù)器對連接的終止。

對于應(yīng)用程序來說,2小時的空閑時間太長。因此,我們需要手工開啟Keepalive功能并設(shè)置合理的Keepalive參數(shù)。

全局設(shè)置可更改 /etc/sysctl.conf ,加上:

net.ipv4.tcp_keepalive_intvl = 20

net.ipv4.tcp_keepalive_probes = 3

net.ipv4.tcp_keepalive_time = 60

在程序中設(shè)置如下:

 
#include <sys/socket.h>  
 #include <netinet/in.h>  
 #include <arpa/inet.h>  
 #include <sys/types.h>  
 #include <netinet/tcp.h>  
  
 int keepAlive = 1; // 開啟keepalive屬性  
 int keepIdle = 60; // 如該連接在60秒內(nèi)沒有任何數(shù)據(jù)往來,則進(jìn)行探測   
 int keepInterval = 5; // 探測時發(fā)包的時間間隔為5 秒  
 int keepCount = 3; // 探測嘗試的次數(shù).如果第1次探測包就收到響應(yīng)了,則后2次的不再發(fā).  
  
 setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));  
 setsockopt(rs, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));  
 setsockopt(rs, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));  
 setsockopt(rs, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));  

在程序中表現(xiàn)為,當(dāng)tcp檢測到對端socket不再可用時(不能發(fā)出探測包,或探測包沒有收到ACK的響應(yīng)包),select會返回socket可讀,并且在recv時返回-1,同時置上errno為ETIMEDOUT.

本文來自互聯(lián)網(wǎng),僅供參考
發(fā)布:2007-04-15 10:00    編輯:泛普軟件 · xiaona    [打印此頁]    [關(guān)閉]
相關(guān)文章:
相關(guān)軟件
聯(lián)系方式

成都公司:成都市成華區(qū)建設(shè)南路160號1層9號

重慶公司:重慶市江北區(qū)紅旗河溝華創(chuàng)商務(wù)大廈18樓

咨詢:400-8352-114

加微信,免費獲取試用系統(tǒng)

QQ在線咨詢