C#基于Socket套接字的網(wǎng)絡(luò)通信封裝
本文為大家分享了C#基于Socket套接字的網(wǎng)絡(luò)通信封裝代碼,供大家參考,具體內(nèi)容如下
摘要
之所以要進(jìn)行Socket套接字通信庫封裝,主要是直接使用套接字進(jìn)行網(wǎng)絡(luò)通信編程相對復(fù)雜,特別對于初學(xué)者而言。實際上微軟從.net 2.0開始已經(jīng)提供了TCP、UDP通信高級封裝類如下:
TcpListener
TcpClient
UdpClient
微軟從.net 4.0開始提供基于Task任務(wù)的異步通信接口。而直接使用socket封裝庫,很多socket本身的細(xì)節(jié)沒辦法自行控制,本文目就是提供一種socket的封裝供參考。文中展示部分封裝了TCP通信庫,UDP封裝也可觸類旁通:
CusTcpListener
CusTcpClient
TCP服務(wù)端
TCP服務(wù)端封裝了服務(wù)端本地綁定、監(jiān)聽、接受客戶端連接,并提供了網(wǎng)絡(luò)數(shù)據(jù)流的接口。完整代碼:
public class CusTcpListener { private IPEndPoint mServerSocketEndPoint; private Socket mServerSocket; private bool isActive; public Socket Server { get { return this.mServerSocket; } } protected bool Active { get { return this.isActive; } } public EndPoint LocalEndpoint { get { if (!this.isActive) { return this.mServerSocketEndPoint; } return this.mServerSocket.LocalEndPoint; } } public NetworkStream DataStream { get { NetworkStream networkStream = null; if (this.Server.Connected) { networkStream = new NetworkStream(this.Server, true); } return networkStream; } } public CusTcpListener(IPEndPoint localEP) { this.mServerSocketEndPoint = localEP; this.mServerSocket = new Socket(this.mServerSocketEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); } public CusTcpListener(string localaddr, int port) { if (localaddr == null) { throw new ArgumentNullException("localaddr"); } this.mServerSocketEndPoint = new IPEndPoint(IPAddress.Parse(localaddr), port); this.mServerSocket = new Socket(this.mServerSocketEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); } public CusTcpListener(int port) { this.mServerSocketEndPoint = new IPEndPoint(IPAddress.Any, port); this.mServerSocket = new Socket(this.mServerSocketEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); } public void Start() { this.Start(int.MaxValue); } /// <summary> /// 開始服務(wù)器監(jiān)聽 /// </summary> /// <param name="backlog">同時等待連接的最大個數(shù)(半連接隊列個數(shù)限制)</param> public void Start(int backlog) { if (backlog > int.MaxValue || backlog < 0) { throw new ArgumentOutOfRangeException("backlog"); } if (this.mServerSocket == null) { throw new NullReferenceException("套接字為空"); } this.mServerSocket.Bind(this.mServerSocketEndPoint); this.mServerSocket.Listen(backlog); this.isActive = true; } public void Stop() { if (this.mServerSocket != null) { this.mServerSocket.Close(); this.mServerSocket = null; } this.isActive = false; this.mServerSocket = new Socket(this.mServerSocketEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); } public Socket AcceptSocket() { Socket socket = this.mServerSocket.Accept(); return socket; } public CusTcpClient AcceptTcpClient() { CusTcpClient tcpClient = new CusTcpClient(this.mServerSocket.Accept()); return tcpClient; } }
TCP客戶端
TCP客戶端封裝了客戶端本地綁定、連接服務(wù)器,并提供了網(wǎng)絡(luò)數(shù)據(jù)流的接口。完整代碼:
public class CusTcpClient : IDisposable { public Socket Client { get; set; } protected bool Active { get; set; } public IPEndPoint ClientSocketEndPoint { get; set; } public bool IsConnected { get { return this.Client.Connected; } } public NetworkStream DataStream { get { NetworkStream networkStream = null; if (this.Client.Connected) { networkStream = new NetworkStream(this.Client, true); } return networkStream; } } public CusTcpClient(IPEndPoint localEP) { if (localEP == null) { throw new ArgumentNullException("localEP"); } this.Client = new Socket(localEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp); this.Active = false; this.Client.Bind(localEP); this.ClientSocketEndPoint = localEP; } public CusTcpClient(string localaddr, int port) { if (localaddr == null) { throw new ArgumentNullException("localaddr"); } IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(localaddr), port); this.Client = new Socket(localEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp); this.Active = false; this.Client.Bind(localEP); this.ClientSocketEndPoint = localEP; } internal CusTcpClient(Socket acceptedSocket) { this.Client = acceptedSocket; this.Active = true; this.ClientSocketEndPoint = (IPEndPoint)this.Client.LocalEndPoint; } public void Connect(string address, int port) { if (address == null) { throw new ArgumentNullException("address"); } IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(address), port); this.Connect(remoteEP); } public void Connect(IPEndPoint remoteEP) { if (remoteEP == null) { throw new ArgumentNullException("remoteEP"); } this.Client.Connect(remoteEP); this.Active = true; } public void Close() { this.Dispose(true); } protected virtual void Dispose(bool disposing) { if (disposing) { IDisposable dataStream = this.DataStream; if (dataStream != null) { dataStream.Dispose(); } else { Socket client = this.Client; if (client != null) { client.Close(); this.Client = null; } } GC.SuppressFinalize(this); } } public void Dispose() { this.Dispose(true); } }
通信實驗
控制臺程序試驗,服務(wù)端程序:
class Program { static void Main(string[] args) { Thread listenerThread = new Thread(ListenerClientConnection); listenerThread.IsBackground = true; listenerThread.Start(); Console.ReadKey(); } private static void ListenerClientConnection() { CusTcpListener tcpListener = new CusTcpListener("127.0.0.1", 5100); tcpListener.Start(); Console.WriteLine("等待客戶端連接……"); while (true) { CusTcpClient tcpClient = tcpListener.AcceptTcpClient(); Console.WriteLine("客戶端接入,ip={0} port={1}", tcpClient.ClientSocketEndPoint.Address, tcpClient.ClientSocketEndPoint.Port); Thread thread = new Thread(DataHandleProcess); thread.IsBackground = true; thread.Start(tcpClient); } } private static void DataHandleProcess(object obj) { CusTcpClient tcpClient = (CusTcpClient)obj; StreamReader streamReader = new StreamReader(tcpClient.DataStream, Encoding.Default); Console.WriteLine("等待客戶端輸入:"); while (true) { try { string receStr = streamReader.ReadLine(); Console.WriteLine(receStr); } catch (Exception) { Console.WriteLine("斷開連接"); break; } Thread.Sleep(5); } } }
客戶端程序:
class Program { static void Main(string[] args) { Thread listenerThread = new Thread(UserProcess); listenerThread.IsBackground = true; listenerThread.Start(); Console.ReadKey(); } private static void UserProcess() { Console.WriteLine("連接服務(wù)器"); CusTcpClient tcpClient = new CusTcpClient("127.0.0.1", 5080); tcpClient.Connect("127.0.0.1", 5100); Console.WriteLine("開始和服務(wù)器通信"); StreamWriter sw = new StreamWriter(tcpClient.DataStream, Encoding.Default); sw.AutoFlush = true; while (true) { for (int i = 0; i < 10; i++) { string str = string.Format("第{0}次,內(nèi)容:{1}", i, "測試通信"); Console.WriteLine("發(fā)送數(shù)據(jù):{0}", str); sw.WriteLine(str); } break; } } }
通信成功:
通過本次封裝演示可實現(xiàn)基于Socket的通信庫封裝,目的就是使用Socket通信庫讓應(yīng)用開發(fā)人員在進(jìn)行網(wǎng)絡(luò)通訊編程時無需關(guān)心底層通訊機(jī)制,而只關(guān)心應(yīng)用層的開發(fā),讓開發(fā)變得更簡潔。當(dāng)然UDP封裝類似,可自行設(shè)計。當(dāng)然本文只是一種示例,實際使用可使用.net自帶封裝庫或自定義封裝。
補(bǔ)充:目前有很多優(yōu)秀的開源Socket框架,比如SuperSocket、FastSocket等。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
c#實現(xiàn)windows遠(yuǎn)程桌面連接程序代碼
本篇文章主要介紹了c#實現(xiàn)windows遠(yuǎn)程桌面連接程序代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05C#如何在窗體程序中操作數(shù)據(jù)庫數(shù)據(jù)
這篇文章主要介紹了C#如何在窗體程序中操作數(shù)據(jù)庫數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04淺析C#數(shù)據(jù)類型轉(zhuǎn)換的幾種形式
本篇文章是對C#中數(shù)據(jù)類型轉(zhuǎn)換的幾種形式進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-07-07C# datatable 不能通過已刪除的行訪問該行的信息處理方法
采用datatable.Rows[i].Delete()刪除行后再訪問該表時出現(xiàn)出現(xiàn)“不能通過已刪除的行訪問該行的信息”的錯誤2012-11-11