在使用乙個長連線的tcp時,如果tcp伺服器端接收到tcp的客戶端連線過來後,接著伺服器端的tcp節點需要對這個客戶端進行資料收發,收發時需要判斷這個socket是否可用用,判斷方法有多種;
1.linux的5種方法,本人在使用modbus伺服器端判斷已經連線的裝置或是gprs伺服器對已經連線的gprs裝置判斷,推薦使用方法2.
法一:當recv()返回值小於等於0時,socket連線斷開。但是還需要判斷 errno是否等於 eintr,如果errno == eintr 則說明recv函式是由於程式接收到訊號後返回的,socket連線還是正常的,不應close掉socket連線。
法二:struct tcp_info info;
int len=sizeof(info);
getsockopt(sock, ipproto_tcp, tcp_info, &info, (socklen_t *)&len);
if((info.tcpi_state==tcp_established)) // 則說明未斷開 else 斷開多種狀態參考後面:
法三:若使用了select等系統函式,若遠端斷開,則select返回1,recv返回0則斷開。其他注意事項同法一。
法四:int keepalive = 1; // 開啟keepalive屬性
int keepidle = 60; // 如該連線在60秒內沒有任何資料往來,則進行探測
int keepinterval = 5; // 探測時發包的時間間隔為5 秒
int keepcount = 3; // 探測嘗試的次數.如果第1次探測包就收到響應了,則後2次的不再發.
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));
設定後,若斷開,則在使用該socket讀寫時立即失敗,並返回etimedout錯誤
法五:自己實現乙個心跳檢測,一定時間內未收到自定義的心跳包則標記為已斷開。
tcp狀態介紹
closed:表示初始狀態。對服務端和c客戶端雙方都一樣。
listen:表示監聽狀態。服務端呼叫了listen函式,可以開始accept連線了。
syn_sent:表示客戶端已經傳送了syn報文。當客戶端呼叫connect函式發起連線時,首先發syn給服務端,然後自己進入syn_sent狀態,並等待服務端傳送ack+syn。
syn_rcvd:表示服務端收到客戶端傳送syn報文。服務端收到這個報文後,進入syn_rcvd狀態,然後傳送ack+syn給客戶端。
established:表示連線已經建立成功了。服務端傳送完ack+syn後進入該狀態,客戶端收到ack後也進入該狀態。
fin_wait_1:表示主動關閉連線。無論哪方呼叫close函式傳送fin報文都會進入這個這個狀態。
fin_wait_2:表示被動關閉方同意關閉連線。主動關閉連線方收到被動關閉方返回的ack後,會進入該狀態。
time_wait:表示收到對方的fin報文並傳送了ack報文,就等2msl後即可回到closed狀態了。如果fin_wait_1狀態下,收到對方同時帶fin標誌和ack標誌的報文時,可以直接進入time_wait狀態,而無須經過fin_wait_2狀態。
closing:表示雙方同時關閉連線。如果雙方幾乎同時呼叫close函式,那麼會出現雙方同時傳送fin報文的情況,此時就會出現closing狀態,表示雙方都在關閉連線。
close_wait:表示被動關閉方等待關閉。當收到對方呼叫close函式傳送的fin報文時,回應對方ack報文,此時進入close_wait狀態。
last_ack:表示被動關閉方傳送fin報文後,等待對方的ack報文狀態,當收到ack後進入closed狀態。
特別提示的是:為什麼time_wait狀態還需要等待2msl才能回到closed狀態?或者為什麼tcp要引入time_wait狀態?
《tcp/ip詳解》中如此解釋:當tcp執行乙個主動關閉,並發回最後乙個ack後,該連線必須在time_wait狀態停留的時間為2倍的msl,這樣可以讓tcp再次傳送最後的ack以防止這個ack丟失(另一端超時重發最後的fin)。
附註:msl(maximum segment lifetime)即最大生存時間,rfc 793中指出msl為2分鐘,但是實現中的常用值為30秒、1分鐘或者2分鐘。
msl是maximum segment lifetime英文的縮寫,中文可以譯為「報文最大生存時間」,他是任何報文在網路上存在的最長時間,超過這個時間報文將被丟棄。因為tcp報文(segment)是ip資料報(datagram)的資料部分,具體稱謂請參見《資料在網路各層中的稱呼》一文,而ip頭中有乙個ttl域,ttl是time to live的縮寫,中文可以譯為「生存時間」,這個生存時間是由源主機設定初始值但不是存的具體時間,而是儲存了乙個ip資料報可以經過的最大路由數,每經過乙個處理他的路由器此值就減1,當此值為0則資料報將被丟棄,同時傳送icmp報文通知源主機。rfc 793中規定msl為2分鐘,實際應用中常用的是30秒,1分鐘和2分鐘等。
2msl即兩倍的msl,tcp的time_wait狀態也稱為2msl等待狀態,當tcp的一端發起主動關閉,在發出最後乙個ack包後,即第3次握手完成後傳送了第四次握手的ack包後就進入了time_wait狀態,必須在此狀態上停留兩倍的msl時間,等待2msl時間主要目的是怕最後乙個ack包對方沒收到,那麼對方在超時後將重發第三次握手的fin包,主動關閉端接到重發的fin包後可以再發乙個ack應答包。在time_wait狀態時兩端的埠不能使用,要等到2msl時間結束才可繼續使用。當連線處於2msl等待階段時任何遲到的報文段都將被丟棄。不過在實際應用中可以通過設定so_reuseaddr選項達到不必等待2msl時間結束再使用此埠。
TCP連線狀態 如何判斷乙個TCP連線是否可用
在使用乙個長連線的tcp時,如果tcp伺服器端接收到tcp的客戶端連線過來後,接著伺服器端的tcp節點需要對這個客戶端進行資料收發,收發時需要判斷這個socket是否可用用,判斷方法有多種 1.linux的5種方法,本人在使用modbus伺服器端判斷已經連線的裝置或是gprs伺服器對已經連線的gpr...
Linux如何判斷乙個tcp連線是否活著
這兩天伺服器網路不穩定,結果發現了乙個現象 乙個tcp連線的服務端 windows 早已停止,而客戶端 linux 的連線狀態卻一直保持為established,直到第二天中午連線才斷開。在網上搜一下,才知道tcp的相關設定 cat proc sys net ipv4 tcp keepalive t...
如何判斷乙個彈框是開啟還是關閉狀態?
1.給彈框設定標記物。將value設定為0 2 當彈框開啟時,將value設定為1 allcomplaintlist status val 1 3.當彈框關閉時,將value設定為0 allcomplaintlist status val 0 場景應用,當彈框顯示的時候,實時請求重新整理頁面資料 關...