• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

c#异步Socket Tcp服务器实现

c# 搞代码 4年前 (2022-01-09) 28次浏览 已收录 0个评论

使用的是TcpListener来实现的异步服务器

代码

服务器核心代码 AsyncServer.cs

/// <summary>      /// 异步SOCKET 服务器      /// </summary>      public class AsyncServer : IDisposable      {            #region Fields          /// <summary>          /// 服务器程序允许的最大客户端连接数          /// </summary>          private int _maxClient;             /// <summary>          /// 当前的连接的客户端数          /// </summary>          private int _clientCount;             /// <summary>          /// 服务器使用的异步socket          /// </summary>          private Socket _serverSock;             /// <summary>          /// 客户端会话列表          /// </summary>          private List _clients;             private bool disposed = false;            #endregion              #region Properties             /// <summary>          /// 服务器是否正在运行          /// </summary>          public bool IsRunning { get; private set; }          /// <summary>          /// 监听的IP地址          /// </summary>          public IPAddress Address { get; private set; }          /// <summary>          /// 监听的端口          /// </summary>          public int Port { get; private set; }          /// <summary>          /// 通信使用的编码          /// </summary>          public Encoding Encoding { get; set; }                      #endregion            #region Ctors             /// <summary>          /// 异步Socket TCP服务器          /// </summary>          /// 监听的端口          public AsyncServer(int listenPort)              : this(IPAddress.Any, listenPort,1024)          {          }             /// <summary>          /// 异步Socket TCP服务器          /// </summary>          /// 监听的终结点          public AsyncServer(IPEndPoint localEP)              : this(localEP.Address, localEP.Port,1024)          {          }             /// <summary>          /// 异步Socket TCP服务器          /// </summary>          /// 监听的IP地址          /// 监听的端口          /// 最大客户端数量          public AsyncServer(IPAddress localIPAddress, int listenPort,int maxClient)          {              this.Address = localIPAddress;              this.Port = listenPort;              this.Encoding = Encoding.Default;                 _maxClient = maxClient;              _clients = new List();              _serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);          }            #endregion         <em>本文来源[email protected]搞@^&代*@码2网</em>     #region Server             /// <summary>          /// 启动服务器          /// </summary>          /// 异步TCP服务器          public AsyncServer Start()          {              if (!IsRunning)              {                  IsRunning = true;                  _serverSock.Bind(new IPEndPoint(this.Address, this.Port));                  _serverSock.Listen(1024);                  _serverSock.BeginAccept(new AsyncCallback(HandleAcceptConnected), _serverSock);              }              return this;          }             /// <summary>          /// 启动服务器          /// </summary>          ///           /// 服务器所允许的挂起连接序列的最大长度          ///           /// 异步TCP服务器          public AsyncServer Start(int backlog)          {              if (!IsRunning)              {                  IsRunning = true;                  _serverSock.Bind(new IPEndPoint(this.Address, this.Port));                  _serverSock.Listen(backlog);                  _serverSock.BeginAccept(new AsyncCallback(HandleAcceptConnected), _serverSock);              }              return this;          }             /// <summary>          /// 停止服务器          /// </summary>          /// 异步TCP服务器          public AsyncServer Stop()          {              if (IsRunning)              {                  IsRunning = false;                  _serverSock.Close();                  //TODO 关闭对所有客户端的连接                 }              return this;          }            #endregion            #region Receive          /// <summary>          /// 处理客户端连接          /// </summary>          ///           private void HandleAcceptConnected(IAsyncResult ar)          {              if (IsRunning)              {                  Socket server = (Socket)ar.AsyncState;                  Socket client = server.EndAccept(ar);                                     //检查是否达到最大的允许的客户端数目                  if (_clientCount == _maxClient)                  {                      //TODO 触发事件                      RaiseServerException(null);                  }                  else                 {                      Session session = new Session(client);                      lock (_clients)                      {                          _clients.Add(session);                          _clientCount++;                          RaiseClientConnected(session); //触发客户端连接事件                      }                      session.RecvDataBuffer = new byte[client.ReceiveBufferSize];                      //开始接受来自该客户端的数据                      client.BeginReceive(session.RecvDataBuffer, 0, session.RecvDataBuffer.Length, SocketFlags.None,                       new AsyncCallback(HandleDataReceived), session);                  }                  //接受下一个请求                  server.BeginAccept(new AsyncCallback(HandleAcceptConnected), ar.AsyncState);              }          }          /// <summary>          /// 处理客户端数据          /// </summary>          ///           private void HandleDataReceived(IAsyncResult ar)          {              if (IsRunning)              {                  Session session = (Session)ar.AsyncState;                  Socket client = session.ClientSocket;                  try                 {                      //如果两次开始了异步的接收,所以当客户端退出的时候                      //会两次执行EndReceive                      int recv = client.EndReceive(ar);                      if (recv == 0)                      {                          //TODO 触发事件 (关闭客户端)                          CloseSession(session);                          RaiseNetError(session);                          return;                      }                      //TODO 处理已经读取的数据 ps:数据在session的RecvDataBuffer中                      RaiseDataReceived(session);                      //TODO 触发数据接收事件                  }                  catch (SocketException ex)                  {                      //TODO 异常处理                      RaiseNetError(session);                  }                  finally                 {                      //继续接收来自来客户端的数据                      client.BeginReceive(session.RecvDataBuffer, 0, session.RecvDataBuffer.Length, SocketFlags.None,                       new AsyncCallback(HandleDataReceived), session);                  }              }          }          #endregion            #region Send          /// <summary>          /// 发送数据          /// </summary>          /// 接收数据的客户端会话          /// 数据报文          public void Send(Session session, byte[] data)          {              Send(session.ClientSocket,data);          }             /// <summary>          /// 异步发送数据至指定的客户端          /// </summary>          /// 客户端          /// 报文          public void Send(Socket client, byte[] data)          {              if (!IsRunning)                  throw new InvalidProgramException("This TCP Scoket server has not been started.");                 if (client == null)                  throw new ArgumentNullException("client");                 if (data == null)                  throw new ArgumentNullException("data");              client.BeginSend(data, 0, data.Length, SocketFlags.None,               new AsyncCallback(SendDataEnd), client);          }             /// <summary>          /// 发送数据完成处理函数          /// </summary>          /// 目标客户端Socket          private void SendDataEnd(IAsyncResult ar)          {              ((Socket)ar.AsyncState).EndSend(ar);          }          #endregion            #region Events          /// <summary>          /// 接收到数据事件          /// </summary>          public event EventHandler DataReceived;             private void RaiseDataReceived(Session session)          {              if (DataReceived != null)              {                  DataReceived(this, new AsyncEventArgs(session));              }          }             /// <summary>          /// 与客户端的连接已建立事件          /// </summary>          public event EventHandler ClientConnected;          /// <summary>          /// 与客户端的连接已断开事件          /// </summary>          public event EventHandler ClientDisconnected;             /// <summary>          /// 触发客户端连接事件          /// </summary>          ///           private void RaiseClientConnected(Session session)          {              if (ClientConnected != null)              {                  ClientConnected(this, new AsyncEventArgs(session));              }          }          /// <summary>          /// 触发客户端连接断开事件          /// </summary>          ///           private void RaiseClientDisconnected(Socket client)          {              if (ClientDisconnected != null)              {                  ClientDisconnected(this, new AsyncEventArgs("连接断开"));              }          }          /// <summary>          /// 网络错误事件          /// </summary>          public event EventHandler NetError;          /// <summary>          /// 触发网络错误事件          /// </summary>          ///           private void RaiseNetError(Session session)          {              if (NetError != null)              {                  NetError(this, new AsyncEventArgs(session));              }          }             /// <summary>          /// 异常事件          /// </summary>          public event EventHandler ServerException;          /// <summary>          /// 触发异常事件          /// </summary>          ///           private void RaiseServerException(Session session)          {              if (ServerException != null)              {                  ServerException(this, new AsyncEventArgs(session));              }          }          #endregion              #region Close          /// <summary>          /// 关闭一个与客户端之间的会话          /// </summary>          /// 需要关闭的客户端会话对象          public void CloseSession(Session session)          {              if (session != null)              {                  session.Datagram = null;                  session.RecvDataBuffer = null;                     _clients.Remove(session);                  _clientCount--;                  //TODO 触发关闭事件                  session.Close();              }          }          /// <summary>          /// 关闭所有的客户端会话,与所有的客户端连接会断开          /// </summary>          public void CloseAllClient()          {              foreach (Session client in _clients)              {                  CloseSession(client);              }              _clientCount = 0;              _clients.Clear();          }             /// <summary>          /// Performs application-defined tasks associated with freeing,           /// releasing, or resetting unmanaged resources.          /// </summary>          public void Dispose()          {              Dispose(true);              GC.SuppressFinalize(this);          }             /// <summary>          /// Releases unmanaged and - optionally - managed resources          /// </summary>          /// true to release           /// both managed and unmanaged resources; false           /// to release only unmanaged resources.          protected virtual void Dispose(bool disposing)          {              if (!this.disposed)              {                  if (disposing)                  {                      try                     {                          Stop();                          if (_serverSock != null)                          {                              _serverSock = null;                          }                      }                      catch (SocketException ex)                      {                          //TODO                          RaiseServerException(null);                      }                  }                  disposed = true;              }          }          #endregion      }

其中使用了一个Session类,来封装对客户端的连接

Session,cs

/// <summary>      /// 客户端与服务器之间的会话类      /// </summary>      public class Session      {          #region 字段          /// <summary>          /// 接收数据缓冲区          /// </summary>          private byte[] _recvBuffer;             /// <summary>          /// 客户端发送到服务器的报文          /// 注意:在有些情况下报文可能只是报文的片断而不完整          /// </summary>          private string _datagram;             /// <summary>          /// 客户端的Socket          /// </summary>          private Socket _clientSock;            #endregion            #region 属性             /// <summary>          /// 接收数据缓冲区           /// </summary>          public byte[] RecvDataBuffer          {              get             {                  return _recvBuffer;              }              set             {                  _recvBuffer = value;              }          }             /// <summary>          /// 存取会话的报文          /// </summary>          public string Datagram          {              get             {                  return _datagram;              }              set             {                  _datagram = value;              }          }             /// <summary>          /// 获得与客户端会话关联的Socket对象          /// </summary>          public Socket ClientSocket          {              get             {                  return _clientSock;                 }          }              #endregion             /// <summary>          /// 构造函数          /// </summary>          /// 会话使用的Socket连接          public Session(Socket cliSock)          {                 _clientSock = cliSock;          }          /// <summary>          /// 关闭会话          /// </summary>          public void Close()          {                 //关闭数据的接受和发送              _clientSock.Shutdown(SocketShutdown.Both);                 //清理资源              _clientSock.Close();          }      }

事件类

class AsyncEventArgs : EventArgs      {          /// <summary>          /// 提示信息          /// </summary>          public string _msg;             public Session _sessions;             /// <summary>          /// 是否已经处理过了          /// </summary>          public bool IsHandled { get; set; }             public AsyncEventArgs(string msg)          {              this._msg = msg;              IsHandled = false;          }          public AsyncEventArgs(Session session)          {              this._sessions = session;              IsHandled = false;          }          public AsyncEventArgs(string msg, Session session)          {              this._msg = msg;              this._sessions = session;              IsHandled = false;          }      }

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:c#异步Socket Tcp服务器实现
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址