C# WinForm實(shí)現(xiàn)Socket異步通訊的步驟詳解
前言
在工作中,我們常常會(huì)用到各種知識(shí)點(diǎn),但有時(shí)用完后就容易遺忘。為了更好地記錄和回顧這些知識(shí),嘗試用筆記的形式將其整理下來(lái),以備后用。
Socket通訊是網(wǎng)絡(luò)編程中非?;A(chǔ)且重要的一部分,它為應(yīng)用程序提供了基于TCP/IP協(xié)議進(jìn)行數(shù)據(jù)傳輸?shù)哪芰Α?/p>
本文將詳細(xì)介紹如何在C#的WinForm應(yīng)用程序中實(shí)現(xiàn)Socket的異步通訊,希望能為有需要的開發(fā)提供一些參考。
Socket 通訊
Socket(套接字)是基于TCP/IP通訊方式封裝好的類。在使用Socket進(jìn)行編程時(shí),需要添加相關(guān)的服務(wù)引用,以下是在C#項(xiàng)目中需要引入的命名空間:
using System.Net; using System.Net.Sockets;
窗體頁(yè)面搭建
在WinForm窗體中,我們搭建一個(gè)簡(jiǎn)單的界面,將窗體分為上下兩個(gè)區(qū)域,上面作為服務(wù)器區(qū),下面作為客戶端區(qū)。
這樣可以在一個(gè)界面中同時(shí)展示服務(wù)器和客戶端的操作。

服務(wù)器類實(shí)現(xiàn)
1、聲明變量
首先,我們需要聲明一些必要的變量,包括IP地址、端口號(hào)、網(wǎng)絡(luò)端點(diǎn)、偵聽連接套接字、通訊套接字以及數(shù)據(jù)緩沖區(qū)等。
同時(shí),定義一個(gè)委托用于顯示消息。
string ip;//IP地址
string port;//端口號(hào)
IPEndPoint endPoint;//網(wǎng)絡(luò)端點(diǎn)
Socket socServer;//偵聽連接套接字
Socket socClient;//通訊套接字
byte[] dataReceived = new byte[50000];
public delegate void delegateDisplayMsg(string type,string msg);
public delegateDisplayMsg OnDisplay;
public SocketServer()
{
socServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
2、偵聽連接函數(shù)
該函數(shù)用于啟動(dòng)服務(wù)器的偵聽功能,綁定指定的IP地址和端口號(hào),并開始接受客戶端的連接請(qǐng)求。
public void StartListen(string ip,string port)
{
this.ip = ip;
this.port = port;
endPoint = new IPEndPoint(IPAddress.Parse(this.ip), int.Parse(port));
socServer.Bind(endPoint);
socServer.Listen(0);
socServer.BeginAccept(new AsyncCallback(OnClientConnect), null);
ShowMsg("Wait Connect");
}
3、接受數(shù)據(jù)函數(shù)
當(dāng)有客戶端連接時(shí),OnClientConnect方法會(huì)被調(diào)用,它接受客戶端的連接并調(diào)用WaitForData方法等待接收數(shù)據(jù)。
OnDataReceived方法用于處理接收到的數(shù)據(jù),將字節(jié)數(shù)組轉(zhuǎn)換為字符串并顯示。
public void OnClientConnect(IAsyncResult asyn)
{
socClient = socServer.EndAccept(asyn);
WaitForData();
ShowMsg("Client Connected " + socClient.RemoteEndPoint.ToString());
}
public void WaitForData()
{
if (socClient != null)
socClient.BeginReceive(dataReceived, 0, dataReceived.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), null);
}
public void OnDataReceived(IAsyncResult asyn)
{
int dataLength = socClient.EndReceive(asyn);
byte[] chars = new byte[dataLength];
Buffer.BlockCopy(dataReceived, 0, chars, 0, dataLength);
string msg = Encoding.ASCII.GetString(chars);
ShowMsg("<=" + msg);
WaitForData();
}
4、發(fā)送數(shù)據(jù)函數(shù)
SendMsg方法用于向客戶端發(fā)送數(shù)據(jù),將字符串轉(zhuǎn)換為字節(jié)數(shù)組后通過(guò)套接字發(fā)送。
public void SendMsg(string msg)
{
byte[] data = Encoding.Default.GetBytes(msg);
socClient.Send(data);
ShowMsg("=>" + msg);
}
客戶端類實(shí)現(xiàn)
1、聲明變量
客戶端類也需要聲明類似的變量,用于存儲(chǔ)服務(wù)器信息、通訊套接字以及數(shù)據(jù)緩沖區(qū)等。
string ip;//IP地址
string port;//端口號(hào)
IPEndPoint endPoint;//網(wǎng)絡(luò)端點(diǎn)
Socket socClient;//通訊套接字
byte[] dataReceived = new byte[50000];//數(shù)據(jù)Buffer
public delegate void delegateDisplayMsg(string type,string msg);
public delegateDisplayMsg OnDisplay;
public SocketClient()
{
socClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
2、連接服務(wù)器函數(shù)
Connect方法用于發(fā)起與服務(wù)器的連接請(qǐng)求。
public void Connect(string ip, string port)
{
this.ip = ip;
this.port = port;
endPoint = new IPEndPoint(IPAddress.Parse(this.ip), int.Parse(port));
socClient.BeginConnect(endPoint, new AsyncCallback(OnToConnected), null);
}
3、接受數(shù)據(jù)函數(shù)
當(dāng)連接成功時(shí),OnToConnected方法會(huì)被調(diào)用,它調(diào)用WaitForData方法等待接收數(shù)據(jù)。OnDataReceived方法的處理邏輯與服務(wù)器端類似。
public void OnToConnected(IAsyncResult asyn)
{
socClient.EndConnect(asyn);
WaitForData();
ShowMsg("Connect Success");
}
public void WaitForData()
{
if (socClient != null)
socClient.BeginReceive(dataReceived, 0, dataReceived.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), null);
}
public void OnDataReceived(IAsyncResult asyn)
{
int dataLenth = socClient.EndReceive(asyn);
byte[] chars = new byte[dataLenth];
Buffer.BlockCopy(dataReceived, 0, chars, 0, dataLenth);
string msg = Encoding.ASCII.GetString(chars);
ShowMsg("<=" + msg);
WaitForData();
}
4、發(fā)送數(shù)據(jù)函數(shù)
與服務(wù)器端的SendMsg方法類似,客戶端的SendMsg方法也用于向服務(wù)器發(fā)送數(shù)據(jù)。
public void SendMsg(string msg)
{
byte[] data = Encoding.Default.GetBytes(msg);
socClient.Send(data);
ShowMsg("=>" + msg);
}
實(shí)例化與事件綁定
在窗體類中,我們需要實(shí)例化服務(wù)器類和客戶端類,并將它們的消息顯示委托綁定到窗體的消息顯示方法上。
public void Init()
{
Server = new SocketServer();
Client = new SocketClient();
Server.OnDisplay += ShowMsg;
Client.OnDisplay += ShowMsg;
}
按鈕點(diǎn)擊事件處理
為窗體上的按鈕添加點(diǎn)擊事件處理函數(shù),實(shí)現(xiàn)服務(wù)器的啟動(dòng)偵聽、客戶端的連接以及數(shù)據(jù)的發(fā)送功能。
private void btn_StartListen_Click(object sender, EventArgs e)
{
Server.StartListen(txt_serverIP.Text.ToString(), txt_serverPort.Text.ToString());
btn_StartListen.BackColor = Color.LimeGreen;
}
private void btn_Connect_Click(object sender, EventArgs e)
{
Client.Connect(txt_clientIP.Text.ToString(), txt_clientPort.Text.ToString());
}
private void btn_serverSend_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
bool isServer = b.Name.Contains("server");
if (isServer)
Server.SendMsg(txt_serverMsg.Text.ToString());
else
Client.SendMsg(txt_clientMsg.Text.ToString());
}
示例效果

總結(jié)
通過(guò)以上步驟,成功在C#的WinForm應(yīng)用程序中實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的Socket異步通訊模型。這個(gè)模型包含了服務(wù)器端和客戶端的基本功能,如偵聽連接、接受數(shù)據(jù)和發(fā)送數(shù)據(jù)等。
然而,在實(shí)際應(yīng)用中,還需要考慮更多的因素,例如通訊異常的處理、通訊協(xié)議的設(shè)計(jì)以及多個(gè)客戶端同時(shí)通訊的情況等。希望本文的示例能為初學(xué)者提供一個(gè)良好的起點(diǎn),也歡迎大家提出寶貴的意見和建議。
以上就是C# WinForm實(shí)現(xiàn)Socket異步通訊的步驟詳解的詳細(xì)內(nèi)容,更多關(guān)于WinForm Socket異步通訊的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#中實(shí)現(xiàn)任意List的全組合算法代碼
這篇文章主要是介紹了.net C# 實(shí)現(xiàn)任意List的全組合算法實(shí)現(xiàn)代碼,需要的朋友可以參考下2013-05-05
C#如何打開選擇文件對(duì)話框和選擇目錄對(duì)話框
這篇文章主要介紹了C#如何打開選擇文件對(duì)話框和選擇目錄對(duì)話框問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
C#中foreach循環(huán)對(duì)比f(wàn)or循環(huán)的優(yōu)勢(shì)和劣勢(shì)
循環(huán)語(yǔ)句是編程的基本語(yǔ)句,在C#中除了沿用C語(yǔ)言的循環(huán)語(yǔ)句外,還提供了foreach語(yǔ)句來(lái)實(shí)現(xiàn)循環(huán),下面這篇文章主要給大家介紹了關(guān)于C#中foreach循環(huán)對(duì)比f(wàn)or循環(huán)的優(yōu)勢(shì)和劣勢(shì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-09-09
C#運(yùn)算符大全_各種運(yùn)算符號(hào)的概述及作用
以下是對(duì)C#中各種運(yùn)算符號(hào)的說(shuō)明及作用進(jìn)行了詳細(xì)的總結(jié)介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-10-10
C#利用Windows自帶gdi32.dll實(shí)現(xiàn)抓取屏幕功能實(shí)例
這篇文章主要介紹了C#利用Windows自帶gdi32.dll實(shí)現(xiàn)抓取屏幕功能,是C#程序設(shè)計(jì)中常見的一個(gè)重要技巧,需要的朋友可以參考下2014-08-08

