斷線檢測
tcp的斷線檢測,是分為兩種的:
① 利用tcp自帶的keep –alive機制
② 自己組建心跳包的方式向對端發送
Keep_alive機制
通過Keep-alive機制對tcp的連接保持,也就是Tcp的心跳包,見MSDN:
If keep-alive is enabled for a TCP socket with SO_KEEPALIVE, then the default TCP settings are used for the keep-alive timeout and interval unless these values have been changed by calling the WSAIoctl function with the SIO_KEEPALIVE_VALS option. The default settings when a TCP socket is initialized sets the keep-alive timeout to 2 hours and the keep-alive interval to 1 second.
也就是說協議棧會在2小時后發送向對端發送請求包。默認情況下,此Keep-alive機制是關閉的。
自己發送心跳包機制
自己發送心跳包,在程序內一般采用多線程,檢測最后發送(或者接收包)的時間,超過一定時間,則發送心跳包。
由此產生疑問:
為什么都是采用的發送的方式?
TCP原理
TCP原理應該都不陌生,但是其本質的還是對端數據包的發送,常聽人說,TCP有鏈路,其實TCP是沒有鏈路的,系統對數據包的判定(判斷從哪個機器的哪個程序發送的),其實是通過(本端ip+本端port+對端ip+對端port)的hash值來判定的,系統根據這個值在協議棧內保存着每個socket的狀態,比如當前接收了多少字節等等信息。
Keep_alive機制默認關閉的影響
Keep-alive默認下是關閉的,也就是本端與對端是除非程序主動send,是不會發送數據包(心跳包),既是,處理本端與對端的系統里的socket狀態是不會變化,這里,如果對端當機(或者網線斷掉),本端是無法知道對端socket已經關閉,所以本端的socket會一直的存在。

if __name__ == ' __main__ ':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(( ' 0.0.0.0 ', 8001))
sock.listen(5)
while True:
print ' here: '
conn, address = sock.accept()
buf = conn.recv(1024)
print ' buf: ' + str(len(buf))
if len(buf) <= 0:
print ' conn close: ', conn
客戶端采用如下步驟:
1, 連接
2, 拔掉網線
經過以上兩步:
從上圖中可以看到,此時服務端的連接依然存在。
所以,tcp只是數據的發送與接收,包括握手,斷開以及rst,time_wait,close_wait 等等。