c#非同步Socket Tcp伺服器實現

來源:互聯網
上載者:User
使用的是TcpListener來實現的非同步伺服器

代碼

伺服器核心代碼 AsyncServer.cs

///       /// 非同步SOCKET 伺服器      ///       public class AsyncServer : IDisposable      {            #region Fields          ///           /// 伺服器程式允許的最大用戶端串連數          ///           private int _maxClient;             ///           /// 當前的串連的用戶端數          ///           private int _clientCount;             ///           /// 伺服器使用的非同步socket          ///           private Socket _serverSock;             ///           /// 用戶端工作階段列表          ///           private List _clients;             private bool disposed = false;            #endregion              #region Properties             ///           /// 伺服器是否正在運行          ///           public bool IsRunning { get; private set; }          ///           /// 監聽的IP地址          ///           public IPAddress Address { get; private set; }          ///           /// 監聽的連接埠          ///           public int Port { get; private set; }          ///           /// 通訊使用的編碼          ///           public Encoding Encoding { get; set; }                      #endregion            #region Ctors             ///           /// 非同步Socket TCP伺服器          ///           /// 監聽的連接埠          public AsyncServer(int listenPort)              : this(IPAddress.Any, listenPort,1024)          {          }             ///           /// 非同步Socket TCP伺服器          ///           /// 監聽的終結點          public AsyncServer(IPEndPoint localEP)              : this(localEP.Address, localEP.Port,1024)          {          }             ///           /// 非同步Socket TCP伺服器          ///           /// 監聽的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              #region Server             ///           /// 啟動伺服器          ///           /// 非同步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;          }             ///           /// 啟動伺服器          ///           ///           /// 伺服器所允許的掛起串連序列的最大長度          ///           /// 非同步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;          }             ///           /// 停止伺服器          ///           /// 非同步TCP伺服器          public AsyncServer Stop()          {              if (IsRunning)              {                  IsRunning = false;                  _serverSock.Close();                  //TODO 關閉對所有用戶端的串連                 }              return this;          }            #endregion            #region Receive          ///           /// 處理用戶端串連          ///           ///           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);              }          }          ///           /// 處理用戶端資料          ///           ///           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          ///           /// 發送資料          ///           /// 接收資料的用戶端工作階段          /// 資料報文          public void Send(Session session, byte[] data)          {              Send(session.ClientSocket,data);          }             ///           /// 非同步發送資料至指定的用戶端          ///           /// 用戶端          /// 報文          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);          }             ///           /// 發送資料完成處理函數          ///           /// 勘探端Socket          private void SendDataEnd(IAsyncResult ar)          {              ((Socket)ar.AsyncState).EndSend(ar);          }          #endregion            #region Events          ///           /// 接收到資料事件          ///           public event EventHandler DataReceived;             private void RaiseDataReceived(Session session)          {              if (DataReceived != null)              {                  DataReceived(this, new AsyncEventArgs(session));              }          }             ///           /// 與用戶端的串連已建立事件          ///           public event EventHandler ClientConnected;          ///           /// 與用戶端的串連已斷開事件          ///           public event EventHandler ClientDisconnected;             ///           /// 觸發用戶端串連事件          ///           ///           private void RaiseClientConnected(Session session)          {              if (ClientConnected != null)              {                  ClientConnected(this, new AsyncEventArgs(session));              }          }          ///           /// 觸發用戶端串連斷開事件          ///           ///           private void RaiseClientDisconnected(Socket client)          {              if (ClientDisconnected != null)              {                  ClientDisconnected(this, new AsyncEventArgs("串連斷開"));              }          }          ///           /// 網路錯誤事件          ///           public event EventHandler NetError;          ///           /// 觸發網路錯誤事件          ///           ///           private void RaiseNetError(Session session)          {              if (NetError != null)              {                  NetError(this, new AsyncEventArgs(session));              }          }             ///           /// 例外狀況事件          ///           public event EventHandler ServerException;          ///           /// 觸發例外狀況事件          ///           ///           private void RaiseServerException(Session session)          {              if (ServerException != null)              {                  ServerException(this, new AsyncEventArgs(session));              }          }          #endregion              #region Close          ///           /// 關閉一個與用戶端之間的會話          ///           /// 需要關閉的用戶端工作階段對象          public void CloseSession(Session session)          {              if (session != null)              {                  session.Datagram = null;                  session.RecvDataBuffer = null;                     _clients.Remove(session);                  _clientCount--;                  //TODO 觸發關閉事件                  session.Close();              }          }          ///           /// 關閉所有的用戶端工作階段,與所有的用戶端串連會斷開          ///           public void CloseAllClient()          {              foreach (Session client in _clients)              {                  CloseSession(client);              }              _clientCount = 0;              _clients.Clear();          }             ///           /// Performs application-defined tasks associated with freeing,           /// releasing, or resetting unmanaged resources.          ///           public void Dispose()          {              Dispose(true);              GC.SuppressFinalize(this);          }             ///           /// Releases unmanaged and - optionally - managed resources          ///           /// 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

///       /// 用戶端與伺服器之間的會話類      ///       public class Session      {          #region 欄位          ///           /// 接收資料緩衝區          ///           private byte[] _recvBuffer;             ///           /// 用戶端發送到伺服器的報文          /// 注意:在有些情況下報文可能只是報文的片斷而不完整          ///           private string _datagram;             ///           /// 用戶端的Socket          ///           private Socket _clientSock;            #endregion            #region 屬性             ///           /// 接收資料緩衝區           ///           public byte[] RecvDataBuffer          {              get             {                  return _recvBuffer;              }              set             {                  _recvBuffer = value;              }          }             ///           /// 存取會話的報文          ///           public string Datagram          {              get             {                  return _datagram;              }              set             {                  _datagram = value;              }          }             ///           /// 獲得與用戶端工作階段關聯的Socket對象          ///           public Socket ClientSocket          {              get             {                  return _clientSock;                 }          }              #endregion             ///           /// 建構函式          ///           /// 會話使用的Socket串連          public Session(Socket cliSock)          {                 _clientSock = cliSock;          }          ///           /// 關閉會話          ///           public void Close()          {                 //關閉資料的接受和發送              _clientSock.Shutdown(SocketShutdown.Both);                 //清理資源              _clientSock.Close();          }      }

事件類別

class AsyncEventArgs : EventArgs      {          ///           /// 提示資訊          ///           public string _msg;             public Session _sessions;             ///           /// 是否已經處理過了          ///           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;          }      }
  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.