最近在做有關於tcp採集程式時,發現在客戶端與伺服器通過tcp socket進行通訊的時候,如果客戶端應用程式正常或者異常退出時,伺服器都可以在對應的socket通訊連線上獲得響應(如返回0,或者丟擲異常)。但是,如果在客戶端的網線被拔掉的情況下,那麼預設情況下,伺服器端需要很長的時間才會知道客戶端的網線斷掉。對於許多伺服器應用程式來說,這麼長的反應時間是不能允許的,在這種情況下通常使用「心跳機制」來解決類似的問題,這是一種可行的辦法。
由於tcp採集程式只是通過長連線來接收訊息,而不能與客戶端建立心跳機制,所以唯一可行的辦法就是設定超時機制,在非阻塞模式工作的情況下,可以通過空閒計數來判斷是否連線超時,在連線空閒情況下tcp採集程式會休眠10ms,並且空閒計數器加1,當收到資料時空閒計數器清零,因此當空閒計數達到3000次的時候,說明socket連線在30秒內沒有收到資料,此時認為連線超時,主動的斷開連線,釋放socket資源。最近在做乙個tcp採集程式,使用到c/s的結構。功能比較的簡單,就是tcp採集程式作為伺服器,信令採集裝置作為客戶端,客戶端與伺服器端之間建立長連線之後,開始傳送信令報文給伺服器。在伺服器端使用多執行緒方式來處理每個客戶端的socket連線,伺服器端不主動斷開鏈路,也沒有心跳機制來維護連線的狀態,客戶端傳送資料的時間也是不一定的,只要有採集到信令資料時才進行傳送。在客戶端socket斷開後,伺服器端應該能夠知道並且釋放socket資源。如何檢查socket是否斷開
判斷socket是否已經斷開的方法是使用非阻塞的select方式進行socket檢查,步驟如下:
1)設定接收到的socket為非同步方式;
2)使用select()函式測試乙個socket是否可讀;
3)如果select()函式返回的值為1,但是使用recv()函式讀取的資料長度為0,那麼說明該socket已經斷開。
如果recv()返回值小於等於0時,客戶端的連線已經斷開,但是還需要判斷errno是否等於eintr。如果errno=eintr則說明recv()函式是由於程式接收到中斷訊號後返回的,socket連線應該還是正常,步應該close掉socket連線。
注:對於阻塞socket的recv函式會在以下三種情況下返回值:
1)接收到資料時會返回;
2)程式接收到訊號時返回-1,errno=eintr;
3)socket出現問題時,返回-1,具體的錯誤碼請檢視man recv;
4)一定要養成檢視man說明,內容很詳細,很有幫助。
此外,unp卷一上有很多socket異常情況下的模擬解釋,大家可以去閱讀下。如果網路中間有多級路由,路由當掉等很多情況出現,所以建議程式中在應用層中加入心跳(heartbeat機制)和重連來維持連線的狀態。
tcp協議有乙個定時器來決定連線是否被異常關閉。但是該超時時間值預設的情況下會非常長,如果你希望盡快的檢查出這種狀態改進效能,最好的方法就是在應用程式協議設計的時候引入keepalive(保持連線)機制。
socket通訊時協議的制定
在系統開發過程中,如果涉及到了socket通訊,那就要制定好通訊的協議,只有制定好了規則,後面的工作才方便順利展開,製作通訊協議時要考慮到通訊的安全性,必要的資訊要經過加密處理,同時也要考慮到系統的可擴充套件性,如果以後需要增加乙個命令或者修改命令要保證這些工作能方便的進行。協議的內容包括如下 一 ...
Flex與Socket通訊時的
昨天開始玩flex,做socket的helloworld時,發現服務端老是提出,連線不了,資料也傳送不了。這是個安全沙箱問題,可網上千篇一律的解決方案根本解決不了問題。剛剛在從度娘那找到一方法終於解決了。flex與c socket通訊服務端收到的簡單解決辦法 開啟資料夾 c windows syst...
VisualC 中託管Socket的實現方法 二
五 利用socket來接收資料 visual c 在使用socket來介紹網路傳送來的資料時,要解決下面三個問題,也是完成visual c 使用socket來接收資料的三個步驟 1.偵聽網路,接受網路連線申請 2.獲得用以接收資料的socket例項,並以此例項接收遠端主機傳送來的資料 3.根據遠端主...