一、本文目的
在涉及網路程式設計的實際專案應用中,由於網路不可能一直處於理想狀態,tcp長連線也可能隨時正常或異常地斷開,如果不予處理,那麼就可能因此而給程式帶來很多潛在的問題。 編寫該文件的目的就在於針對網路程式中可能遇到的各種問題,拿出來與大家**一下具體問題的解決方案,同時本人將前期調研的一些解決方案列出來,拋磚引玉,希望可以集思廣益,尋求到更加合理的解決方案。
二、網路斷開時機
1、正常網路斷開
(1) cs 一方呼叫 close
(2) cs 一方程式正常退出,如ctrl + c 事件可以被系統檢測到,對應的套接字
也將被系統標記為已斷開。
2、異常網路斷開
(1) cs 一方網線被撥出
(2) cs 之間路由
故障,物理連線斷開
(3) cs 一方斷電或當機
(4) cs 一方無線訊號不佳或無線介面被關閉
三、網路斷開常用檢測方法
1、處理正常網路斷開
(1) select 捕捉可讀事件,read返回0
(2) epoll 捕捉可讀事件,read返回0
(3) 主動 read 返回錯誤
(4) 主動 write 返回錯誤
2、處理異常網路斷開
(1) 應用層keepalive檢測
(2) 傳輸層keepalive檢測
除了應用層 keepalive 檢測機制外,tcp 內部也整合了 keepalive 機制,預設關閉,開啟它很方便。對端跟自身出現網路故障都能檢測到。但不是所有的系統都支援,而且有些系統雖然支援但會影響到所有套接字,消耗額外的寬頻和流量,不建議使用。
[cpp]view plain
copy
//啟用心跳機制,如果您想關閉,將keepalive置零即可
setsockopt(fd,sol_socket,so_keepalive,(void
*)&keepalive,
sizeof
(keepalive));
//啟用心跳機制開始到首次心跳偵測包傳送之間的空閒時間
setsockopt(fd,sol_tcp,tcp_keepidle,(void
*)&start,
sizeof
(start));
//兩次心跳偵測包之間的間隔時間
setsockopt(fd,sol_tcp,tcp_keepintvl,(void
*)&interval,
sizeof
(interval));
//探測次數,即將幾次探測失敗判定為tcp斷開
setsockopt(fd,sol_tcp,tcp_keepcnt,(void
*)&count,
sizeof
(count));
(3) 網路層keepalive檢測
ping 命令幾乎是所有平台的網路連通性檢測命令,走網路層 icmp 協議,這裡考慮使用 popen 函式呼叫系統自帶的 ping 命令來封裝網路連通性檢測函式。它實際上也是一種網路層的 keepalive 機制。
[cpp]view plain
copy
intcheckconnect(
char
*dst,
intcnt)
[cpp]view plain
copy
dst 指定要檢測的目的位址,cnt 指定 ping 嘗試的次數,-i 引數指定 ping 嘗試的超時時間。
(4) 應用層監控核心訊息機制
netlink 是一種特殊的套接字,為2.6.14及更高版本的linux所特有,通過它,應用層程式可以方便地向核心訂製指定訊息,如網絡卡上下線。也可以設定或查詢配置,如ip、路由、網路流量資訊等。
a、建立乙個 netlink 套接字:
[cpp]view plain
copy
fd = socket(af_netlink, sock_raw, netlink_route);
b、繫結路由多播組,監控網絡卡資訊:
[cpp]view plain
copy
addr.nl_family = af_netlink;
addr.nl_groups = rtnlgrp_link; //指定接收路由多播組訊息
bind(fd, (struct
sockaddr*)&addr,
sizeof
(addr));
c、監聽套接字,一旦可讀,解析其內容,實時監控網絡卡上下線事件。
優點:實時性高,使用方便。
缺點:跨平台性不佳,只能檢測自身網路故障。
(5) 應用層網絡卡資訊輪詢機制
網絡卡資訊輪詢機制就是定期呼叫 ioctl 函式執行如下操作:
[cpp]view plain
copy
struct
ifconf ifc;
struct
ifreq ifrcopy;
//獲取網絡卡資訊列表
ioctl(fd, siocgifconf, (char
*)&ifc);
//獲取網絡卡上下線狀態
ioctl(fd, siocgifflags, &ifrcopy);
//獲取 mac 位址
ioctl(fd, siocgifhwaddr, (char
*)(&ifrcopy);
//獲取 ip 位址
ioctl(fd, siocgifaddr, (char
*)&ifrcopy);
//獲取廣播位址
ioctl(fd, siocgifbrdaddr, &ifrcopy));
缺點:a、跨平台性不佳。
可以成功移植到 linux、android
、windows
平台,但由於 iphone
平台上獲取mac跟ip的引數不同,需特殊處理。
b、實時性跟靈活性不高。
c、耗費資源,影響效能。
d、只能檢測自身網路故障。
網路程式設計(一)網路程式設計入門
網路是計算機通訊的基礎,網路程式設計是學習計算機網路最佳方法,通常標準的計算機網路通訊協議有udp和tcp兩種 此處不包含微計算機網路通訊協議 如can等 首先小猿引入幾個面試常見的問題。1 網路程式設計三要素是什麼?答 網路程式設計的三要素是,ip,傳輸協議,埠號。2 網路模型有幾種?如何理解?答...
網路程式設計(一) 網路基礎之一
今天開始學習網路程式設計,當然還是要從網路基礎學起,首先我們來熟悉一下tcp ip模型與osi模型之間的對應關係 一.tcp ip四層模型 tcp ip是 一組協議的代名詞,它還包括許多協議,組成了tcp ip協議簇。tcp ip協議簇 分為四層,ip位於協議簇的第 二層 對應osi的第三層 tcp...
Windows程式設計 網路概念(一) 網路分層
ps 這些文字是參考的unp寫的,但是網路分層的原理都是一樣的,並且懶得專門去寫乙個關於windows的了,所以就這樣 網路是分層的,程式設計師關心的是以下4層 在談論網路資料的時候,如果說到幀,則應該知道是乙太網層。我們一般關心的是tcp 分節,應用層 訊息。tcp ip協議不僅僅指的是tcp協議...