C#中一个高性能异步socket封装库的实现思路分享

2019-12-30 18:35:44丽君

库的使用

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


using IocpCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace WarningClient
{
 public class SocketServer
 {
  public Action<SocketEventParam> OnSocketEvent;

  public Int64 SendByteCount
  {
   get
   {
    if (_netServer == null)
     return 0;
    return _netServer.SendByteCount;
   }
  }
  public Int64 ReadByteCount
  {
   get
   {
    if (_netServer == null)
     return 0;
    return _netServer.ReadByteCount;
   }
  }

  NetServer _netServer;
  EN_PacketType _packetType = EN_PacketType.byteStream;
  public void SetPacktType(EN_PacketType packetType)
  {
   _packetType = packetType;
   if (_netServer == null)
    return;
   if (packetType == EN_PacketType.byteStream)
   {
    _netServer.SetPacketParam(0, 1024);
   }
   else
   {
    _netServer.SetPacketParam(9, 1024);
   }
  }

  public bool Init(List<int> listenPort)
  {
   NetLogger.OnLogEvent += NetLogger_OnLogEvent;
   _netServer = new NetServer();
   SetPacktType(_packetType);
   _netServer.GetPacketTotalLen_Callback += GetPacketTotalLen;
   _netServer.OnSocketPacketEvent += SocketPacketDeal;

   foreach (int n in listenPort)
   {
    _netServer.AddListenPort(n, n);
   }

   List<int> listenFault;
   bool start = _netServer.StartListen(out listenFault);
   return start;
  }

  int GetPacketTotalLen(byte[] data, int offset)
  {
   if (MainWindow._packetType == EN_PacketType.znss)
    return GetPacketZnss(data, offset);
   else
    return GetPacketAnzhiyuan(data, offset);
  }

  int GetPacketAnzhiyuan(byte[] data, int offset)
  {
   int n = data[offset + 5] + 6;
   return n;
  }

  int GetPacketZnss(byte[] data, int offset)
  {
   int packetLen = (int)(data[4]) + 5;
   return packetLen;
  }


  public bool ConnectAsyn(string peerIp, int peerPort, object tag)
  {
   return _netServer.ConnectAsyn(peerIp, peerPort, tag);
  }

  public bool Connect(string peerIp, int peerPort, object tag, out Socket socket)
  {
   return _netServer.Connect(peerIp, peerPort, tag, out socket);
  }

  private void NetLogger_OnLogEvent(string message)
  {
   AppLog.Log(message);
  }

  Dictionary<Socket, SocketEventParam> _clientGroup = new Dictionary<Socket, SocketEventParam>();

  public int ClientCount
  {
   get
   {
    lock (_clientGroup)
    {
     return _clientGroup.Count;
    }
   }
  }
  public List<Socket> ClientList
  {
   get
   {
    if (_netServer != null)
     return _netServer.ClientList;
    return new List<Socket>();
   }
  }
  void AddClient(SocketEventParam socketParam)
  {
   lock (_clientGroup)
   {
    _clientGroup.Remove(socketParam.Socket);
    _clientGroup.Add(socketParam.Socket, socketParam);
   }
  }

  void RemoveClient(SocketEventParam socketParam)
  {
   lock (_clientGroup)
   {
    _clientGroup.Remove(socketParam.Socket);
   }
  }

  ObjectPool<SocketEventParam> _readDataPool = new ObjectPool<SocketEventParam>();

  public ObjectPool<SocketEventParam> ReadDataPool
  {
   get
   {
    return _readDataPool;
   }
  }

  private void SocketPacketDeal(SocketEventParam socketParam)
  {
   OnSocketEvent?.Invoke(socketParam);
   if (socketParam.SocketEvent == EN_SocketEvent.read)
   {
    if (MainWindow._isShowReadPacket)
     _readDataPool.PutObj(socketParam);
   }
   else if (socketParam.SocketEvent == EN_SocketEvent.accept)
   {
    AddClient(socketParam);
    string peerIp = socketParam.ClientInfo.PeerIpPort;
    AppLog.Log(string.Format("客户端链接!本地端口:{0},对端:{1}",
     socketParam.ClientInfo.LocalPort, peerIp));
   }
   else if (socketParam.SocketEvent == EN_SocketEvent.connect)
   {
    string peerIp = socketParam.ClientInfo.PeerIpPort;
    if (socketParam.Socket != null)
    {
     AddClient(socketParam);

     AppLog.Log(string.Format("连接对端成功!本地端口:{0},对端:{1}",
      socketParam.ClientInfo.LocalPort, peerIp));
    }
    else
    {
     AppLog.Log(string.Format("连接对端失败!本地端口:{0},对端:{1}",
      socketParam.ClientInfo.LocalPort, peerIp));
    }
   }
   else if (socketParam.SocketEvent == EN_SocketEvent.close)
   {
    MainWindow.MainWnd.OnSocketDisconnect(socketParam.Socket);
    RemoveClient(socketParam);
    string peerIp = socketParam.ClientInfo.PeerIpPort;
    AppLog.Log(string.Format("客户端断开!本地端口:{0},对端:{1},",
     socketParam.ClientInfo.LocalPort, peerIp));
   }
  }

  public EN_SendDataResult SendData(Socket socket, byte[] data)
  {
   if(socket == null)
   {
    MessageBox.Show("还没连接!");
    return EN_SendDataResult.no_client;
   }
   return _netServer.SendData(socket, data);
  }

  internal void SendToAll(byte[] data)
  {
   lock (_clientGroup)
   {
    foreach (Socket socket in _clientGroup.Keys)
    {
     SendData(socket, data);
    }
   }
  }
 }
}