C#基于Socket套接字的網(wǎng)絡(luò)通信封裝
本文為大家分享了C#基于Socket套接字的網(wǎng)絡(luò)通信封裝代碼,供大家參考,具體內(nèi)容如下
摘要
之所以要進(jìn)行Socket套接字通信庫封裝,主要是直接使用套接字進(jìn)行網(wǎng)絡(luò)通信編程相對(duì)復(fù)雜,特別對(duì)于初學(xué)者而言。實(shí)際上微軟從.net 2.0開始已經(jīng)提供了TCP、UDP通信高級(jí)封裝類如下:
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í)等待連接的最大個(gè)數(shù)(半連接隊(duì)列個(gè)數(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);
}
}
通信實(shí)驗(yàn)
控制臺(tái)程序試驗(yàn),服務(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;
}
}
}
通信成功:

通過本次封裝演示可實(shí)現(xiàn)基于Socket的通信庫封裝,目的就是使用Socket通信庫讓應(yīng)用開發(fā)人員在進(jìn)行網(wǎng)絡(luò)通訊編程時(shí)無需關(guān)心底層通訊機(jī)制,而只關(guān)心應(yīng)用層的開發(fā),讓開發(fā)變得更簡潔。當(dāng)然UDP封裝類似,可自行設(shè)計(jì)。當(dāng)然本文只是一種示例,實(shí)際使用可使用.net自帶封裝庫或自定義封裝。
補(bǔ)充:目前有很多優(yōu)秀的開源Socket框架,比如SuperSocket、FastSocket等。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Unity實(shí)現(xiàn)車型識(shí)別的示例代碼
這篇文章主要介紹了在Unity中接入百度AI,實(shí)現(xiàn)檢測一張車輛圖片的具體車型。即對(duì)于輸入的一張圖片(可正常解碼,且長寬比適宜),輸出圖片的車輛品牌及型號(hào)。需要的可以參考一下2022-01-01
C#自動(dòng)生成漂亮的水晶效果頭像的實(shí)現(xiàn)代碼
這篇文章主要介紹了C#自動(dòng)生成漂亮的水晶效果頭像的實(shí)現(xiàn)代碼,有需要的朋友可以參考一下2013-12-12
c#實(shí)現(xiàn)windows遠(yuǎn)程桌面連接程序代碼
本篇文章主要介紹了c#實(shí)現(xiàn)windows遠(yuǎn)程桌面連接程序代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
C#如何在窗體程序中操作數(shù)據(jù)庫數(shù)據(jù)
這篇文章主要介紹了C#如何在窗體程序中操作數(shù)據(jù)庫數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
淺析C#數(shù)據(jù)類型轉(zhuǎn)換的幾種形式
本篇文章是對(duì)C#中數(shù)據(jù)類型轉(zhuǎn)換的幾種形式進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-07-07
C# datatable 不能通過已刪除的行訪問該行的信息處理方法
采用datatable.Rows[i].Delete()刪除行后再訪問該表時(shí)出現(xiàn)出現(xiàn)“不能通過已刪除的行訪問該行的信息”的錯(cuò)誤2012-11-11

