今天工作時發現當Clinet端不正常斷線時, Server端竟然不知道!!!!
不知道Client端已經不存在了, 笨笨的繼續傳遞資料給Client(是我笨吧…Orz)
當然會導致程式發生Exception……….
Server真的會不知道嗎~~會他當然會知道 但是預設為兩小時後[1]~這早就發生Exception…
經過[1]中發現, 原來可以設定
Keep-Alive來保持Socket長連接, 並且偵測網路異常拋出Exception
當Client端發生不正常斷線時, Server端將會立刻知道~~~
Keep-Alive使用方法寫在Comment裡嚕~ 這裡紀錄一下
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
using
System.Net.Sockets;using
System.Net;public
class ServerSocketObject{ public
Socket ClientToServerSocket; private
Socket ListenSocket; private
IPEndPoint ServerIPEndPoint; public
ManualResetEvent BeginAccpetControl=new
ManualResetEvent(false); //========================== private
Boolean IsBeginAccept = true
; public
List<byte> Reply_Message =
new List<byte>(); public
ServerSocketObject() {
string LocalIP = Dns.GetHostByName(Dns.GetHostName()).AddressList[0].ToString();
ServerIPEndPoint = new
IPEndPoint(IPAddress.Parse(LocalIP), 2266);
ListenSocket = new
Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ListenSocket.Bind(ServerIPEndPoint);
ListenSocket.Listen(1); //ip pool 設為 1
ListenSocket.IOControl(IOControlCode.KeepAliveValues, KeepAlive(1, 1000, 1000),
null);
//將這個Socket使用<b style="background: rgb(255, 102, 255); color: rgb(0, 0, 0);">keep</b>-alive來保持長連線
//KeepAlive函數參數說明: onOff:是否開啟<b style="background: rgb(255, 102, 255); color: rgb(0, 0, 0);">Keep</b>-Alive(開 1/ 關 0) ,
//keepAliveTime:當開啟<b style="background: rgb(255, 102, 255); color: rgb(0, 0, 0);">keep</b>-Alive後經過多久時間(ms)開啟偵測
//keepAliveInterval: 多久偵測一次(ms) } private
byte[] KeepAlive(int
onOff, int
keepAliveTime, int
keepAliveInterval) {
byte[] buffer =
new byte[12];
BitConverter.GetBytes(onOff).CopyTo(buffer, 0);
BitConverter.GetBytes(keepAliveTime).CopyTo(buffer, 4);
BitConverter.GetBytes(keepAliveInterval).CopyTo(buffer, 8);
return buffer; } public
void BeginAccept() {
while (IsBeginAccept)
{
BeginAccpetControl.Reset();
ListenSocket.BeginAccept(new
AsyncCallback(BeginAcceptCallBack), ListenSocket);
BeginAccpetControl.WaitOne(); //等待Clinet...
}
//=================== } private
void BeginAcceptCallBack(IAsyncResult state) {
Socket Listener = (Socket)state.AsyncState;
ClientToServerSocket = Listener.EndAccept(state);
//Client連線成功
ClientToServerSocket.BeginReceive(buffer, 0, BufferSize, 0,
new AsyncCallback(ReceivedCallBack), ClientToServerSocket);
//連線成功後 開始接收Server所傳遞的資料
BeginAccpetControl.Set(); } private
void ReceivedCallBack(IAsyncResult ar) {
Socket state = (Socket)ar.AsyncState;
if (state.Connected ==
true)
{
try
{
int bytesRead = state.EndReceive(ar);
if (bytesRead > 0)
//當 bytesRead大於0時表示Server傳遞資料過來 等於0時代表Client"正常"斷線
{
for (int
num = 0; num < bytesRead; num++)
{
Reply_Message.Add(buffer[num]); //收集資料
}
state.BeginReceive(buffer, 0, BufferSize, 0,
new AsyncCallback(ReceivedCallBack), ClientToServerSocket);
}
else
{
//處理Client端"正常"斷線的事件
}
}
catch (Exception ee)
{
//這裡就是當設定好<b style="background: rgb(255, 102, 255); color: rgb(0, 0, 0);">Keep</b>-alive後, 假設Clinet端發生"不正常斷線(網路異常)"時, 將會
//跑進來這個Exception裡,再加以處理
state.Shutdown(SocketShutdown.Both);
state.Close();
}
}
else
{
IsConntect = false;
state.Close();
} }} |
本文介绍了一种解决客户端异常断线时服务器无法及时发现的问题的方法,通过设置TCP连接的Keep-Alive选项来实现异常情况下的快速检测,并提供了一个具体的C#实现案例。

被折叠的 条评论
为什么被折叠?



