[C#] 利用Keep-alive來保持Socket長連接,並偵測網路異常

今天工作時發現當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();
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值