本文介紹
在上一篇部落格中我說了,我將會介紹c#中使用Socket和TcpListener和UdpClient實現各種同步和非同步TCP和UDP伺服器,這些都是是我自己花了很多天的時間來總結的,這樣一來相信剛接觸c#網路編程的朋友們不會像以前的我一樣到處出找資料,到處調試。本次我介紹的是使用Socket來實現的同步的TCP伺服器,同步的TCP伺服器和第一篇裡面介紹的非同步TCP伺服器的區別就是,在Socket調用Accept的時候是否會阻塞。
同步的TCP伺服器在接受到一個用戶端的請求的時候一般是開啟一個線程去處理和這個用戶端的通訊工作,這種方式的不好的地方就是資源消耗大,但是假如使用線程池的話,事先分配一定數量的線程,效能還是可以。
但是我之所以給出很多方法實現的伺服器,主要目的就是想測試哪種情況效能比較不錯,就目前來看,非同步模式比較NICE,但是其實還有一種IOCP模式效能是最好的。。。
Socket同步TCP伺服器
服務端代碼
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net.Sockets;using System.Net;using System.Threading;namespace NetFrame.Net.TCP.Sock.Synchronous{ /// <summary> /// 基於socket實現的同步TCP伺服器 /// </summary> public class SocketTCPServer { #region Fields /// <summary> /// 伺服器程式允許的最大用戶端串連數 /// </summary> private int _maxClient; /// <summary> /// 當前的串連的用戶端數 /// </summary> private int _clientCount; /// <summary> /// 伺服器使用的非同步socket /// </summary> private Socket _serverSock; /// <summary> /// 用戶端工作階段列表 /// </summary> private List<SocketClientHandle> _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 建構函式 /// <summary> /// 同步Socket TCP伺服器 /// </summary> /// <param name="listenPort">監聽的連接埠</param> public SocketTCPServer(int listenPort) : this(IPAddress.Any, listenPort, 1024) { } /// <summary> /// 同步Socket TCP伺服器 /// </summary> /// <param name="localEP">監聽的終結點</param> public SocketTCPServer(IPEndPoint localEP) : this(localEP.Address, localEP.Port, 1024) { } /// <summary> /// 同步Socket TCP伺服器 /// </summary> /// <param name="localIPAddress">監聽的IP地址</param> /// <param name="listenPort">監聽的連接埠</param> /// <param name="maxClient">最大用戶端數量</param> public SocketTCPServer(IPAddress localIPAddress, int listenPort, int maxClient) { this.Address = localIPAddress; this.Port = listenPort; this.Encoding = Encoding.Default; _maxClient = maxClient; _clients = new List<SocketClientHandle>(); _serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); } #endregion #region Method /// <summary> /// 啟動伺服器 /// </summary> public void Start() { if (!IsRunning) { IsRunning = true; _serverSock.Bind(new IPEndPoint(this.Address, this.Port)); Thread thread = new Thread(StartListen); thread.Start(); } } /// <summary> /// 開始進行監聽 /// </summary> private void StartListen() { _serverSock.Listen(1024); SocketClientHandle handle; while (IsRunning) { if (_clientCount >= _maxClient) { //TODO 用戶端過多異常 RaiseOtherException(null); } else { Socket clientSock = _serverSock.Accept(); _clientCount++; //TODO 建立一個處理用戶端的線程並啟動 handle = new SocketClientHandle(clientSock); _clients.Add(handle); //使用線程池來操作 ThreadPool.QueueUserWorkItem(new WaitCallback(handle.RecevieData)); //Thread pthread; //pthread = new Thread(new ThreadStart(client.RecevieData)); //pthread.Start(); //這裡應該使用線程池來進行 } } } /// <summary> /// 停止伺服器 /// </summary> public void Stop() { if (IsRunning) { IsRunning = false; _serverSock.Close(); //TODO 關閉對所有用戶端的串連 } } /// <summary> /// 發送函數 /// </summary> public void Send(string msg, SocketClientHandle client) { //TODO } /// <summary> /// 關閉一個與用戶端之間的會話 /// </summary> /// <param name="handle">需要關閉的用戶端工作階段對象</param> public void Close(SocketClientHandle handle) { if (handle != null) { _clients.Remove(handle); handle.Dispose(); _clientCount--; //TODO 觸發關閉事件 } } /// <summary> /// 關閉所有的用戶端工作階段,與所有的用戶端串連會斷開 /// </summary> public void CloseAllClient() { foreach (SocketClientHandle handle in _clients) { Close(handle); } _clientCount = 0; _clients.Clear(); } #endregion #region 事件 /// <summary> /// 與用戶端的串連已建立事件 /// </summary> public event EventHandler<SocketEventArgs> ClientConnected; /// <summary> /// 與用戶端的串連已斷開事件 /// </summary> public event EventHandler<SocketEventArgs> ClientDisconnected; /// <summary> /// 觸發用戶端串連事件 /// </summary> /// <param name="state"></param> private void RaiseClientConnected(SocketClientHandle handle) { if (ClientConnected != null) { ClientConnected(this, new SocketEventArgs(handle)); } } /// <summary> /// 觸發用戶端串連斷開事件 /// </summary> /// <param name="client"></param> private void RaiseClientDisconnected(Socket client) { if (ClientDisconnected != null) { ClientDisconnected(this, new SocketEventArgs("串連斷開")); } } /// <summary> /// 接收到資料事件 /// </summary> public event EventHandler<SocketEventArgs> DataReceived; private void RaiseDataReceived(SocketClientHandle handle) { if (DataReceived != null) { DataReceived(this, new SocketEventArgs(handle)); } } /// <summary> /// 資料發送事件 /// </summary> public event EventHandler<SocketEventArgs> CompletedSend; /// <summary> /// 觸發資料發送事件 /// </summary> /// <param name="state"></param> private void RaiseCompletedSend(SocketClientHandle handle) { if (CompletedSend != null) { CompletedSend(this, new SocketEventArgs(handle)); } } /// <summary> /// 網路錯誤事件 /// </summary> public event EventHandler<SocketEventArgs> NetError; /// <summary> /// 觸發網路錯誤事件 /// </summary> /// <param name="state"></param> private void RaiseNetError(SocketClientHandle handle) { if (NetError != null) { NetError(this, new SocketEventArgs(handle)); } } /// <summary> /// 例外狀況事件 /// </summary> public event EventHandler<SocketEventArgs> OtherException; /// <summary> /// 觸發例外狀況事件 /// </summary> /// <param name="state"></param> private void RaiseOtherException(SocketClientHandle handle, string descrip) { if (OtherException != null) { OtherException(this, new SocketEventArgs(descrip, handle)); } } private void RaiseOtherException(SocketClientHandle handle) { RaiseOtherException(handle, ""); } #endregion #region Close 未實現 #endregion #region 釋放 /// <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> /// <param name="disposing"><c>true</c> to release /// both managed and unmanaged resources; <c>false</c> /// to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { try { Stop(); if (_serverSock != null) { _serverSock = null; } } catch (SocketException) { //TODO 異常 } } disposed = true; } } #endregion }}
對用戶端操作封裝的Handle類
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net.Sockets;namespace NetFrame.Net.TCP.Sock.Synchronous{ /// <summary> /// Socket 伺服器用於處理用戶端串連封裝的用戶端處理類 /// </summary> public class SocketClientHandle:IDisposable { /// <summary> /// 與用戶端相關聯的socket /// </summary> private Socket _client; /// <summary> /// 標識是否與用戶端相串連 /// </summary> private bool _is_connect; public bool IsConnect { get { return _is_connect; } set { _is_connect = value; } } /// <summary> /// 資料接受緩衝區 /// </summary> private byte[] _recvBuffer; public SocketClientHandle(Socket client) { this._client = client; _is_connect = true; _recvBuffer = new byte[1024 * 1024 * 2]; } #region Method /// <summary> /// 接受來自用戶端發來的資料 /// </summary> public void RecevieData(Object state) { int len = -1; while (_is_connect) { try { len = _client.Receive(_recvBuffer); } catch (Exception) { //TODO } } } /// <summary> /// 向用戶端發送資料 /// </summary> public void SendData(string msg) { byte[] data = Encoding.Default.GetBytes(msg); try { //有一種比較好的寫法 _client.Send(data); } catch (Exception) { //TODO 處理異常 } } #endregion #region 事件 //TODO 訊息發送事件 //TODO 資料收到事件 //TODO 異常處理事件 #endregion #region 釋放 /// <summary> /// Performs application-defined tasks associated with freeing, /// releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { _is_connect = false; if (_client != null) { _client.Close(); _client = null; } GC.SuppressFinalize(this); } #endregion }}
Socket同步TCP伺服器的時間參數類
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace NetFrame.Net.TCP.Sock.Synchronous{ /// <summary> /// 同步Socket TCP伺服器事件類別 /// </summary> public class SocketEventArgs : EventArgs { /// <summary> /// 提示資訊 /// </summary> public string _msg; /// <summary> /// 用戶端狀態封裝類 /// </summary> public SocketClientHandle _handle; /// <summary> /// 是否已經處理過了 /// </summary> public bool IsHandled { get; set; } public SocketEventArgs(string msg) { this._msg = msg; IsHandled = false; } public SocketEventArgs(SocketClientHandle handle) { this._handle = handle; IsHandled = false; } public SocketEventArgs(string msg, SocketClientHandle handle) { this._msg = msg; this._handle = handle; IsHandled = false; } }}
以上就是C#網路編程系列文章(二)之Socket實現同步TCP伺服器的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!