一个高性能异步socket封装库的实现思路 (c#)

前言

socket是软件之间通讯最常用的一种方式。c#实现socket通讯有很多中方法,其中效率最高就是异步通讯。

异步通讯实际是利用windows完成端口(IOCP)来处理的,关于完成端口实现原理,大家可以参考网上文章。

我这里想强调的是采用完成端口机制的异步通讯是windows下效率最高的通讯方式,没有之一!

 

异步通讯比同步通讯处理要难很多,代码编写中会遇到许多“坑“。如果没有经验,很难完成。

我搜集了大量资料,完成了对异步socket的封装。此库已用稳定高效的运行几个月。

 

纵观网上的资料,我还没有遇到一个满意的封装库。许多文章把数据收发和协议处理杂糅在一块,代码非常难懂,也无法扩展。

在编写该库时,避免以上缺陷。将逻辑处理层次化,模块化!同时实现了高可用性与高性能。

 

为了使大家对通讯效率有初步了解,先看测试图。

一个高性能异步socket封装库的实现思路 (c#)_第1张图片

一个高性能异步socket封装库的实现思路 (c#)_第2张图片

客户端和服务端都是本机测试,最大连接数为64422,套接字已耗尽!

主机配置情况

一个高性能异步socket封装库的实现思路 (c#)_第3张图片

百兆带宽基本占满,cpu占用40%,我的电脑在空闲时,cpu占用大概20%,也就是说程序占用cpu 20%左右。

这个库是可扩展的,就是说即使10万个连接,收发同样的数据,cpu占用基本相同。

 

库的结构图 

一个高性能异步socket封装库的实现思路 (c#)_第4张图片

目标

  1. 即可作为服务端(监听)也可以作为客户端(主动连接)使用。
  2. 可以适应任何网络协议。收发的数据针对字节流或一个完整的包。对协议内容不做处理。
  3. 高可用性。将复杂的底层处理封装,对外接口非常友好。
  4. 高性能。最大限度优化处理。单机可支持数万连接,收发速度可达几百兆bit。

实现思路

网络处理逻辑可以分为以下几个部分:

  1. 网络监听   可以在多个端口实现监听。负责生成socket,生成的socket供后续处理。监听模块功能比较单一,如有必要,可对监听模块做进一步优化。
  2. 主动连接  可以异步或同步的连接对方。连接成功后,对socket的后续处理,与监听得到的socket完全一样。注:无论是监听得到的socket,还是连接得到的socket,后续处理完全一样。
  3. Socket收发处理   每个socket对应一个收发实例,socket收发只针对字节流处理。收发时,做了优化。比如发送时,对数据做了沾包,提高发送性能;接收时,一次投递1K的数据。
  4. 组包处理   一般数据包都有包长度指示;比如 报头的前俩个字节表示长度,根据这个值就可以组成一个完整的包。

 NetListener 监听

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace IocpCore
{
    class NetListener
    {
        private Socket listenSocket;
        public ListenParam _listenParam { get; set; }
        public event Action OnAcceptSocket;

        bool start;

        NetServer _netServer;
        public NetListener(NetServer netServer)
        {
            _netServer = netServer;
        }

        public int _acceptAsyncCount = 0;
        public bool StartListen()
        {
            try
            {
                start = true;
                IPEndPoint listenPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), _listenParam._port);
                listenSocket = new Socket(listenPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                listenSocket.Bind(listenPoint);
                listenSocket.Listen(200);

                Thread thread1 = new Thread(new ThreadStart(NetProcess));
                thread1.Start();
               
                StartAccept();
                return true;
            }
            catch (Exception ex)
            {
                NetLogger.Log(string.Format("**监听异常!{0}", ex.Message));
                return false;
            }
        }

        AutoResetEvent _acceptEvent = new AutoResetEvent(false);
        private void NetProcess()
        {
            while (start)
            {
                DealNewAccept();
                _acceptEvent.WaitOne(1000 * 10);
            }
        }

        private void DealNewAccept()
        {
            try
            {
                if(_acceptAsyncCount <= 10)
                {
                    StartAccept();
                }

                while (true)
                {
                    AsyncSocketClient client = _newSocketClientList.GetObj();
                    if (client == null)
                        break;

                    DealNewAccept(client);
                }
            }
            catch (Exception ex)
            {
                NetLogger.Log(string.Format("DealNewAccept 异常 {0}***{1}", ex.Message, ex.StackTrace));
            }
        }

        private void DealNewAccept(AsyncSocketClient client)
        {
            client.SendBufferByteCount = _netServer.SendBufferBytePerClient;
           OnAcceptSocket?.Invoke(_listenParam, client);
        }

        private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs acceptEventArgs)
        {
            try
            {
                Interlocked.Decrement(ref _acceptAsyncCount);
                _acceptEvent.Set();
                acceptEventArgs.Completed -= AcceptEventArg_Completed;
                ProcessAccept(acceptEventArgs);
            }
            catch (Exception ex)
            {
                NetLogger.Log(string.Format("AcceptEventArg_Completed {0}***{1}", ex.Message, ex.StackTrace));
            }
        }

        public bool StartAccept()
        {
            SocketAsyncEventArgs acceptEventArgs = new SocketAsyncEventArgs();
            acceptEventArgs.Completed += AcceptEventArg_Completed;

            bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArgs);
            Interlocked.Increment(ref _acceptAsyncCount);

            if (!willRaiseEvent)
            {
                Interlocked.Decrement(ref _acceptAsyncCount);
                _acceptEvent.Set();
                acceptEventArgs.Completed -= AcceptEventArg_Completed;
                ProcessAccept(acceptEventArgs);
            }
            return true;
        }

        ObjectPool _newSocketClientList = new ObjectPool();
        private void ProcessAccept(SocketAsyncEventArgs acceptEventArgs)
        {
            try
            {
                using (acceptEventArgs)
                {
                    if (acceptEventArgs.AcceptSocket != null)
                    {
                        AsyncSocketClient client = new AsyncSocketClient(acceptEventArgs.AcceptSocket);
                        client.CreateClientInfo(this);

                        _newSocketClientList.PutObj(client);
                        _acceptEvent.Set();
                    }
                }
            }
            catch (Exception ex)
            {
                NetLogger.Log(string.Format("ProcessAccept {0}***{1}", ex.Message, ex.StackTrace));
            }
        }
    }
}

  

NetConnectManage连接处理

  1 using System;
  2 using System.Net;
  3 using System.Net.Sockets;
  4 
  5 namespace IocpCore
  6 {
  7     class NetConnectManage
  8     {
  9         public event Action OnSocketConnectEvent;
 10 
 11         public bool ConnectAsyn(string peerIp, int peerPort, object tag)
 12         {
 13             try
 14             {
 15                 Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
 16                 SocketAsyncEventArgs socketEventArgs = new SocketAsyncEventArgs();
 17                 socketEventArgs.RemoteEndPoint = new IPEndPoint(IPAddress.Parse(peerIp), peerPort);
 18                 socketEventArgs.Completed += SocketConnect_Completed;
 19 
 20                 SocketClientInfo clientInfo = new SocketClientInfo();
 21                 socketEventArgs.UserToken = clientInfo;
 22                 clientInfo.PeerIp = peerIp;
 23                 clientInfo.PeerPort = peerPort;
 24                 clientInfo.Tag = tag;
 25 
 26                 bool willRaiseEvent = socket.ConnectAsync(socketEventArgs);
 27                 if (!willRaiseEvent)
 28                 {
 29                     ProcessConnect(socketEventArgs);
 30                     socketEventArgs.Completed -= SocketConnect_Completed;
 31                     socketEventArgs.Dispose();
 32                 }
 33                 return true;
 34             }
 35             catch (Exception ex)
 36             {
 37                 NetLogger.Log("ConnectAsyn",ex);
 38                 return false;
 39             }
 40         }
 41 
 42         private void SocketConnect_Completed(object sender, SocketAsyncEventArgs socketEventArgs)
 43         {
 44             ProcessConnect(socketEventArgs);
 45             socketEventArgs.Completed -= SocketConnect_Completed;
 46             socketEventArgs.Dispose();
 47         }
 48 
 49         private void ProcessConnect(SocketAsyncEventArgs socketEventArgs)
 50         {
 51             SocketClientInfo clientInfo = socketEventArgs.UserToken as SocketClientInfo;
 52             if (socketEventArgs.SocketError == SocketError.Success)
 53             {
 54                 DealConnectSocket(socketEventArgs.ConnectSocket, clientInfo);
 55             }
 56             else
 57             {
 58                 SocketEventParam socketParam = new SocketEventParam(EN_SocketEvent.connect, null);
 59                 socketParam.ClientInfo = clientInfo;
 60                 OnSocketConnectEvent?.Invoke(socketParam, null);
 61             }
 62         }
 63 
 64 
 65         void DealConnectSocket(Socket socket, SocketClientInfo clientInfo)
 66         {
 67             clientInfo.SetClientInfo(socket);
 68 
 69             AsyncSocketClient client = new AsyncSocketClient(socket);
 70             client.SetClientInfo(clientInfo);
 71 
 72             //触发事件
 73             SocketEventParam socketParam = new SocketEventParam(EN_SocketEvent.connect, socket);
 74             socketParam.ClientInfo = clientInfo;
 75             OnSocketConnectEvent?.Invoke(socketParam, client);
 76         }
 77 
 78         public bool Connect(string peerIp, int peerPort, object tag, out Socket socket)
 79         {
 80             socket = null;
 81             try
 82             {
 83                 Socket socketTmp = new Socket(SocketType.Stream, ProtocolType.Tcp);
 84 
 85                 SocketClientInfo clientInfo = new SocketClientInfo();
 86                 clientInfo.PeerIp = peerIp;
 87                 clientInfo.PeerPort = peerPort;
 88                 clientInfo.Tag = tag;
 89 
 90                 EndPoint remoteEP = new IPEndPoint(IPAddress.Parse(peerIp), peerPort);
 91                 socketTmp.Connect(remoteEP);
 92                 if (!socketTmp.Connected)
 93                     return false;
 94 
 95                 DealConnectSocket(socketTmp, clientInfo);
 96                 socket = socketTmp;
 97                 return true;
 98             }
 99             catch (Exception ex)
100             {
101                 NetLogger.Log(string.Format("连接对方:({0}:{1})出错!", peerIp, peerPort), ex);
102                 return false;
103             }
104         }
105     }
106 }

View Code

AsyncSocketClient socket收发处理

NetServer  聚合其他类

 

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Diagnostics;
  4 using System.Linq;
  5 using System.Net.Sockets;
  6 using System.Threading;
  7 
  8 namespace IocpCore
  9 {
 10     public class NetServer
 11     {
 12         public Action OnSocketPacketEvent;
 13 
 14         //每个连接发送缓冲大小
 15         public int SendBufferBytePerClient { get; set; } = 1024 * 100;
 16 
 17         bool _serverStart = false;
 18         List _listListener = new List();
 19 
 20         //负责对收到的字节流 组成完成的包
 21         ClientPacketManage _clientPacketManage;
 22 
 23         public Int64 SendByteCount { get; set; }
 24         public Int64 ReadByteCount { get; set; }
 25 
 26         List _listListenPort = new List();
 27         public void AddListenPort(int port, object tag)
 28         {
 29             _listListenPort.Add(new ListenParam(port, tag));
 30         }
 31         /// 
 32         /// 
 33         /// 
 34         /// 监听失败的端口
 35         /// 
 36         public bool StartListen(out List listenFault)
 37         {
 38             _serverStart = true;
 39 
 40             _clientPacketManage = new ClientPacketManage(this);
 41             _clientPacketManage.OnSocketPacketEvent += PutClientPacket;
 42 
 43             _netConnectManage.OnSocketConnectEvent += SocketConnectEvent;
 44 
 45             _listListener.Clear();
 46             Thread thread1 = new Thread(new ThreadStart(NetPacketProcess));
 47             thread1.Start();
 48 
 49             Thread thread2 = new Thread(new ThreadStart(NetSendProcess));
 50             thread2.Start();
 51 
 52             Thread thread3 = new Thread(new ThreadStart(NetReadProcess));
 53             thread3.Start();
 54 
 55             listenFault = new List();
 56             foreach (ListenParam param in _listListenPort)
 57             {
 58                 NetListener listener = new NetListener(this);
 59                 listener._listenParam = param;
 60                 listener.OnAcceptSocket += Listener_OnAcceptSocket;
 61                 if (!listener.StartListen())
 62                 {
 63                     listenFault.Add(param._port);
 64                 }
 65                 else
 66                 {
 67                     _listListener.Add(listener);
 68                     NetLogger.Log(string.Format("监听成功!端口:{0}", param._port));
 69                 }
 70             }
 71 
 72             return listenFault.Count == 0;
 73         }
 74 
 75         public void PutClientPacket(SocketEventParam param)
 76         {
 77             OnSocketPacketEvent?.Invoke(param);
 78         }
 79 
 80         //获取包的最小长度
 81         int _packetMinLen;
 82         int _packetMaxLen;
 83         public int PacketMinLen
 84         {
 85             get { return _packetMinLen; }
 86         }
 87         public int PacketMaxLen
 88         {
 89             get { return _packetMaxLen; }
 90         }
 91 
 92         /// 
 93         /// 设置包的最小和最大长度
 94         /// 当minLen=0时,认为是接收字节流
 95         /// 
 96         /// 
 97         /// 
 98         public void SetPacketParam(int minLen, int maxLen)
 99         {
100             Debug.Assert(minLen >= 0);
101             Debug.Assert(maxLen > minLen);
102             _packetMinLen = minLen;
103             _packetMaxLen = maxLen;
104         }
105 
106         //获取包的总长度
107         public delegate int delegate_GetPacketTotalLen(byte[] data, int offset);
108         public delegate_GetPacketTotalLen GetPacketTotalLen_Callback;
109 
110         ObjectPoolWithEvent _socketEventPool = new ObjectPoolWithEvent();
111         private void NetPacketProcess()
112         {
113             while (_serverStart)
114             {
115                 try
116                 {
117                     DealEventPool();
118                 }
119                 catch (Exception ex)
120                 {
121                     NetLogger.Log(string.Format("DealEventPool 异常 {0}***{1}", ex.Message, ex.StackTrace));
122                 }
123                 _socketEventPool.WaitOne(1000);
124             }
125         }
126 
127         Dictionary _clientGroup = new Dictionary();
128         public int ClientCount
129         {
130             get
131             {
132                 lock (_clientGroup)
133                 {
134                     return _clientGroup.Count;
135                 }
136             }
137         }
138         public List ClientList
139         {
140             get
141             {
142                 lock (_clientGroup)
143                 {
144                     return _clientGroup.Keys.ToList();
145                 }
146             }
147         }
148 
149         private void DealEventPool()
150         {
151             while (true)
152             {
153                 SocketEventParam param = _socketEventPool.GetObj();
154                 if (param == null)
155                     return;
156 
157                 if (param.SocketEvent == EN_SocketEvent.close)
158                 {
159                     lock (_clientGroup)
160                     {
161                         _clientGroup.Remove(param.Socket);
162                     }
163                 }
164 
165                 if (_packetMinLen == 0)//字节流处理
166                 {
167                     OnSocketPacketEvent?.Invoke(param);
168                 }
169                 else
170                 {
171                     //组成一个完整的包 逻辑
172                     _clientPacketManage.PutSocketParam(param);
173                 }
174             }
175         }
176 
177         private void SocketConnectEvent(SocketEventParam param, AsyncSocketClient client)
178         {
179             try
180             {
181                 if (param.Socket == null || client == null) //连接失败
182                 {
183                    
184                 }
185                 else
186                 {
187                     lock (_clientGroup)
188                     {
189                         bool remove = _clientGroup.Remove(client.ConnectSocket);
190                         Debug.Assert(!remove);
191                         _clientGroup.Add(client.ConnectSocket, client);
192                     }
193 
194                     client.OnSocketClose += Client_OnSocketClose;
195                     client.OnReadData += Client_OnReadData;
196                     client.OnSendData += Client_OnSendData;
197 
198                     _listReadEvent.PutObj(new SocketEventDeal(client, EN_SocketDealEvent.read));
199                 }
200                 _socketEventPool.PutObj(param);
201             }
202             catch (Exception ex)
203             {
204                 NetLogger.Log(string.Format("SocketConnectEvent 异常 {0}***{1}", ex.Message, ex.StackTrace));
205             }
206         }
207 
208         internal void OnRcvPacketLenError(Socket socket, byte[] buffer, int offset, int packetLen)
209         {
210             try
211             {
212                 lock (_clientGroup)
213                 {
214                     if (!_clientGroup.ContainsKey(socket))
215                     {
216                         Debug.Assert(false);
217                         return;
218                     }
219 
220                     NetLogger.Log(string.Format("报长度异常!包长:{0}", packetLen));
221                     AsyncSocketClient client = _clientGroup[socket];
222                     client.CloseSocket();
223                 }
224             }
225             catch (Exception ex)
226             {
227                 NetLogger.Log(string.Format("OnRcvPacketLenError 异常 {0}***{1}", ex.Message, ex.StackTrace));
228             }
229         }
230 
231         #region listen port
232         private void Listener_OnAcceptSocket(ListenParam listenPatam, AsyncSocketClient client)
233         {
234             try
235             {
236                 lock (_clientGroup)
237                 {
238                     bool remove = _clientGroup.Remove(client.ConnectSocket);
239                     Debug.Assert(!remove);
240                     _clientGroup.Add(client.ConnectSocket, client);
241                 }
242 
243                 client.OnSocketClose += Client_OnSocketClose;
244                 client.OnReadData += Client_OnReadData;
245                 client.OnSendData += Client_OnSendData;
246 
247                 _listReadEvent.PutObj(new SocketEventDeal(client, EN_SocketDealEvent.read));
248 
249                 SocketEventParam param = new SocketEventParam(EN_SocketEvent.accept, client.ConnectSocket);
250                 param.ClientInfo = client.ClientInfo;
251 
252                 _socketEventPool.PutObj(param);
253             }
254             catch (Exception ex)
255             {
256                 NetLogger.Log(string.Format("Listener_OnAcceptSocket 异常 {0}***{1}", ex.Message, ex.StackTrace));
257             }
258         }
259 
260 
261         ObjectPoolWithEvent _listSendEvent = new ObjectPoolWithEvent();
262         private void NetSendProcess()
263         {
264             while (true)
265             {
266                 DealSendEvent();
267                 _listSendEvent.WaitOne(1000);
268             }
269         }
270 
271         ObjectPoolWithEvent _listReadEvent = new ObjectPoolWithEvent();
272         private void NetReadProcess()
273         {
274             while (true)
275             {
276                 DealReadEvent();
277                 _listReadEvent.WaitOne(1000);
278             }
279         }
280 
281         
282         private void DealSendEvent()
283         {
284             while (true)
285             {
286                 SocketEventDeal item = _listSendEvent.GetObj();
287                 if (item == null)
288                     break;
289                 switch (item.SocketEvent)
290                 {
291                     case EN_SocketDealEvent.send:
292                         {
293                             while (true)
294                             {
295                                 EN_SocketSendResult result = item.Client.SendNextData();
296                                 if (result == EN_SocketSendResult.HaveSend)
297                                     continue;
298                                 else
299                                     break;
300                             }
301                         }
302                         break;
303                     case EN_SocketDealEvent.read:
304                         {
305                             Debug.Assert(false);
306                         }
307                         break;                   
308                 }
309             }
310         }
311 
312         private void DealReadEvent()
313         {
314             while (true)
315             {
316                 SocketEventDeal item = _listReadEvent.GetObj();
317                 if (item == null)
318                     break;
319                 switch (item.SocketEvent)
320                 {
321                     case EN_SocketDealEvent.read:
322                         {
323                             while (true)
324                             {
325                                 EN_SocketReadResult result = item.Client.ReadNextData();
326                                 if (result == EN_SocketReadResult.HaveRead)
327                                     continue;
328                                 else
329                                     break;
330                             }
331                         }
332                         break;
333                     case EN_SocketDealEvent.send:
334                         {
335                             Debug.Assert(false);
336                         }
337                         break;
338                 }
339             }
340         }
341 
342         private void Client_OnReadData(AsyncSocketClient client, byte[] readData)
343         {
344             //读下一条
345             _listReadEvent.PutObj(new SocketEventDeal(client, EN_SocketDealEvent.read));
346 
347             try
348             {
349                 SocketEventParam param = new SocketEventParam(EN_SocketEvent.read, client.ConnectSocket);
350                 param.ClientInfo = client.ClientInfo;
351                 param.Data = readData;
352                 _socketEventPool.PutObj(param);
353 
354                 lock (this)
355                 {
356                     ReadByteCount += readData.Length;
357                 }
358             }
359             catch (Exception ex)
360             {
361                 NetLogger.Log(string.Format("Client_OnReadData 异常 {0}***{1}", ex.Message, ex.StackTrace));
362             }
363         }
364 #endregion
365 
366         private void Client_OnSendData(AsyncSocketClient client, int sendCount)
367         {
368             //发送下一条
369             _listSendEvent.PutObj(new SocketEventDeal(client, EN_SocketDealEvent.send));
370             lock (this)
371             {
372                 SendByteCount += sendCount;
373             }
374         }
375 
376         private void Client_OnSocketClose(AsyncSocketClient client)
377         {
378             try
379             {
380                 SocketEventParam param = new SocketEventParam(EN_SocketEvent.close, client.ConnectSocket);
381                 param.ClientInfo = client.ClientInfo;
382                 _socketEventPool.PutObj(param);
383             }
384             catch (Exception ex)
385             {
386                 NetLogger.Log(string.Format("Client_OnSocketClose 异常 {0}***{1}", ex.Message, ex.StackTrace));
387             }
388         }
389 
390         /// 
391         /// 放到发送缓冲
392         /// 
393         /// 
394         /// 
395         /// 
396         public EN_SendDataResult SendData(Socket socket, byte[] data)
397         {
398             if (socket == null)
399                 return EN_SendDataResult.no_client;
400             lock (_clientGroup)
401             {
402                 if (!_clientGroup.ContainsKey(socket))
403                     return EN_SendDataResult.no_client;
404                 AsyncSocketClient client = _clientGroup[socket];
405                 EN_SendDataResult result = client.PutSendData(data);
406                 if (result == EN_SendDataResult.ok)
407                 {
408                     //发送下一条
409                     _listSendEvent.PutObj(new SocketEventDeal(client, EN_SocketDealEvent.send));                  
410                 }
411                 return result;
412             }
413         }
414 
415         /// 
416         /// 设置某个连接的发送缓冲大小
417         /// 
418         /// 
419         /// 
420         /// 
421         public bool SetClientSendBuffer(Socket socket, int byteCount)
422         {
423             lock (_clientGroup)
424             {
425                 if (!_clientGroup.ContainsKey(socket))
426                     return false;
427                 AsyncSocketClient client = _clientGroup[socket];
428                 client.SendBufferByteCount = byteCount;
429                 return true;
430             }
431         }
432 
433 
434         #region connect process
435         NetConnectManage _netConnectManage = new NetConnectManage();
436         /// 
437         /// 异步连接一个客户端
438         /// 
439         /// 
440         /// 
441         /// 
442         /// 
443         public bool ConnectAsyn(string peerIp, int peerPort, object tag)
444         {
445             return _netConnectManage.ConnectAsyn(peerIp, peerPort, tag);
446         }
447 
448         /// 
449         /// 同步连接一个客户端
450         /// 
451         /// 
452         /// 
453         /// 
454         /// 
455         /// 
456         public bool Connect(string peerIp, int peerPort, object tag, out Socket socket)
457         {
458             return _netConnectManage.Connect(peerIp, peerPort, tag, out socket);
459         }
460         #endregion
461     }
462 
463     enum EN_SocketDealEvent
464     {
465         read,
466         send,
467     }
468     class SocketEventDeal
469     {
470         public AsyncSocketClient Client { get; set; }
471         public EN_SocketDealEvent SocketEvent { get; set; }
472         public SocketEventDeal(AsyncSocketClient client, EN_SocketDealEvent socketEvent)
473         {
474             Client = client;
475             SocketEvent = socketEvent;
476         }
477     }
478 }

View Code

 

库的使用

使用起来非常简单,示例如下 

  1 using IocpCore;
  2 using System;
  3 using System.Collections.Generic;
  4 using System.Linq;
  5 using System.Net.Sockets;
  6 using System.Text;
  7 using System.Threading.Tasks;
  8 using System.Windows;
  9 
 10 namespace WarningClient
 11 {
 12     public class SocketServer
 13     {
 14         public Action OnSocketEvent;
 15 
 16         public Int64 SendByteCount
 17         {
 18             get
 19             {
 20                 if (_netServer == null)
 21                     return 0;
 22                 return _netServer.SendByteCount;
 23             }
 24         }
 25         public Int64 ReadByteCount
 26         {
 27             get
 28             {
 29                 if (_netServer == null)
 30                     return 0;
 31                 return _netServer.ReadByteCount;
 32             }
 33         }
 34 
 35         NetServer _netServer;
 36         EN_PacketType _packetType = EN_PacketType.byteStream;
 37         public void SetPacktType(EN_PacketType packetType)
 38         {
 39             _packetType = packetType;
 40             if (_netServer == null)
 41                 return;
 42             if (packetType == EN_PacketType.byteStream)
 43             {
 44                 _netServer.SetPacketParam(0, 1024);
 45             }
 46             else
 47             {
 48                 _netServer.SetPacketParam(9, 1024);
 49             }
 50         }
 51 
 52         public bool Init(List listenPort)
 53         {
 54             NetLogger.OnLogEvent += NetLogger_OnLogEvent;
 55             _netServer = new NetServer();
 56             SetPacktType(_packetType);
 57             _netServer.GetPacketTotalLen_Callback += GetPacketTotalLen;
 58             _netServer.OnSocketPacketEvent += SocketPacketDeal;
 59 
 60             foreach (int n in listenPort)
 61             {
 62                 _netServer.AddListenPort(n, n);
 63             }
 64 
 65             List listenFault;
 66             bool start = _netServer.StartListen(out listenFault);
 67             return start;
 68         }
 69 
 70         int GetPacketTotalLen(byte[] data, int offset)
 71         {
 72             if (MainWindow._packetType == EN_PacketType.znss)
 73                 return GetPacketZnss(data, offset);
 74             else
 75                 return GetPacketAnzhiyuan(data, offset);
 76         }
 77 
 78         int GetPacketAnzhiyuan(byte[] data, int offset)
 79         {
 80             int n = data[offset + 5] + 6;
 81             return n;
 82         }
 83 
 84         int GetPacketZnss(byte[] data, int offset)
 85         {
 86             int packetLen = (int)(data[4]) + 5;
 87             return packetLen;
 88         }
 89 
 90 
 91         public bool ConnectAsyn(string peerIp, int peerPort, object tag)
 92         {
 93             return _netServer.ConnectAsyn(peerIp, peerPort, tag);
 94         }
 95 
 96         public bool Connect(string peerIp, int peerPort, object tag, out Socket socket)
 97         {
 98             return _netServer.Connect(peerIp, peerPort, tag, out socket);
 99         }
100 
101         private void NetLogger_OnLogEvent(string message)
102         {
103             AppLog.Log(message);
104         }
105 
106         Dictionary _clientGroup = new Dictionary();
107 
108         public int ClientCount
109         {
110             get
111             {
112                 lock (_clientGroup)
113                 {
114                     return _clientGroup.Count;
115                 }
116             }
117         }
118         public List ClientList
119         {
120             get
121             {
122                 if (_netServer != null)
123                     return _netServer.ClientList;
124                 return new List();
125             }
126         }
127         void AddClient(SocketEventParam socketParam)
128         {
129             lock (_clientGroup)
130             {
131                 _clientGroup.Remove(socketParam.Socket);
132                 _clientGroup.Add(socketParam.Socket, socketParam);
133             }
134         }
135 
136         void RemoveClient(SocketEventParam socketParam)
137         {
138             lock (_clientGroup)
139             {
140                 _clientGroup.Remove(socketParam.Socket);
141             }
142         }
143 
144         ObjectPool _readDataPool = new ObjectPool();
145 
146         public ObjectPool ReadDataPool
147         {
148             get
149             {
150                 return _readDataPool;
151             }
152         }
153 
154         private void SocketPacketDeal(SocketEventParam socketParam)
155         {
156             OnSocketEvent?.Invoke(socketParam);
157             if (socketParam.SocketEvent == EN_SocketEvent.read)
158             {
159                 if (MainWindow._isShowReadPacket)
160                     _readDataPool.PutObj(socketParam);
161             }
162             else if (socketParam.SocketEvent == EN_SocketEvent.accept)
163             {
164                 AddClient(socketParam);
165                 string peerIp = socketParam.ClientInfo.PeerIpPort;
166                 AppLog.Log(string.Format("客户端链接!本地端口:{0},对端:{1}",
167                     socketParam.ClientInfo.LocalPort, peerIp));
168             }
169             else if (socketParam.SocketEvent == EN_SocketEvent.connect)
170             {
171                 string peerIp = socketParam.ClientInfo.PeerIpPort;
172                 if (socketParam.Socket != null)
173                 {
174                     AddClient(socketParam);
175 
176                     AppLog.Log(string.Format("连接对端成功!本地端口:{0},对端:{1}",
177                        socketParam.ClientInfo.LocalPort, peerIp));
178                 }
179                 else
180                 {
181                     AppLog.Log(string.Format("连接对端失败!本地端口:{0},对端:{1}",
182                         socketParam.ClientInfo.LocalPort, peerIp));
183                 }
184             }
185             else if (socketParam.SocketEvent == EN_SocketEvent.close)
186             {
187                 MainWindow.MainWnd.OnSocketDisconnect(socketParam.Socket);
188                 RemoveClient(socketParam);
189                 string peerIp = socketParam.ClientInfo.PeerIpPort;
190                 AppLog.Log(string.Format("客户端断开!本地端口:{0},对端:{1},",
191                     socketParam.ClientInfo.LocalPort, peerIp));
192             }
193         }
194 
195         public EN_SendDataResult SendData(Socket socket, byte[] data)
196         {
197             if(socket == null)
198             {
199                 MessageBox.Show("还没连接!");
200                 return EN_SendDataResult.no_client;
201             }
202             return _netServer.SendData(socket, data);
203         }
204 
205         internal void SendToAll(byte[] data)
206         {
207             lock (_clientGroup)
208             {
209                 foreach (Socket socket in _clientGroup.Keys)
210                 {
211                     SendData(socket, data);
212                 }
213             }
214         }
215     }
216 }

View Code

 技术交流联系qq 13712486

你可能感兴趣的:(c#,socket)