C# 網路連線中異常斷線的處理:ReceiveTimeout, SendTimeout 及 KeepAliveValues(設定心跳)
在使用 TcpClient 網路連線中常常會發生客戶端連線異常斷開, 服務端需要設定檢測手段進行這種異常的處理.
對於短連線, 通過對 Socket 屬性 ReceiveTimeout 和 SendTimeout 設定適當的值, 當在進行讀/寫時超時, 則會產生 SocketException 異常, 通過檢查這個異常並進行處理. 如下服務端連線處理程式碼示例:
while (newClient.Connected && isConnected)
{
ns.ReadTimeout
newClient.Client.SendTimeout = 1000;
int bytesRead = 0;
try
{
bytesRead = ns.Read(buffer, 0, buffer.Length); // 讀取資料, 根據內容進行回覆
if (bytesRead == 1)
{
//string receiveInfo = Encoding.ASCII.GetString(buffer, 0, bytesRead);
CmdType cmd = (CmdType)buffer[0];
connect.ReceiveInfo = cmd.ToString(); // 儲存儲存的資訊
if (ReceiveData != null)
{
EventArgs e = new EventArgs();
ReceiveData(this, e);
}
ns.ReadTimeout = 1000; // decrease to 1s
//響應請求 response
string response = "hello";
buffer = Encoding.UTF8.GetBytes(String.Format("[{0:d4}] {1}", id, response));
ns.Write(buffer, 0, buffer.Length);
}
Thread.Sleep(100);
}
catch
{
bytesRead = 0;
isConnected = false; // 異常則立即終止連線
}
}
newClient.Close();
對於長連線可以通過 Socket 中的心跳檢測機制進行處理.
Socket的底層IO一般通過 WSAIoctl 函式進行設定. C# 中對此函式進行了封裝, 即 Socket.IOControl 方法.
public int IOControl( IOControlCode ioControlCode, byte[] optionInValue, byte[] optionOutValue )
其中第一個引數為 Socket IO 控制程式碼; 第二個引數為傳入引數值, 第三個引數為傳出值.
在Winsock 2 中定義了許多 Socket IO 控制型別 , 其中有一項: KeepAliveValues , 控制 TCP keep-alive 資料包的傳送以及傳送間隔。預設值為2個小時, 當間隔時間超過這個設定後, socket就會連續傳送5次連線訊號, 若客戶端無迴應, 則此 client socket會斷開.
我們可以如下調整這個間隔時間:
newClient.Client.IOControl(IOControlCode.KeepAliveValues, BitConverter.GetBytes(120), null); // 設定為 2分鐘.
以上即為2種網路異常連線斷線檢測的方法.