C# WinForm實(shí)現(xiàn)Socket異步通訊的步驟詳解
前言
在工作中,我們常常會(huì)用到各種知識(shí)點(diǎn),但有時(shí)用完后就容易遺忘。為了更好地記錄和回顧這些知識(shí),嘗試用筆記的形式將其整理下來,以備后用。
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;
窗體頁面搭建
在WinForm窗體中,我們搭建一個(gè)簡單的界面,將窗體分為上下兩個(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ù)組后通過套接字發(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é)
通過以上步驟,成功在C#的WinForm應(yīng)用程序中實(shí)現(xiàn)了一個(gè)簡單的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)汽車租賃系統(tǒng)項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)汽車租賃系統(tǒng)項(xiàng)目,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
使用C# Winform應(yīng)用程序獲取網(wǎng)頁源文件的解決方法
本篇文章是對(duì)使用C# Winform應(yīng)用程序獲取網(wǎng)頁源文件的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C#實(shí)現(xiàn)OpenOffice(ODT/ODS/ODP)到Microsoft Office(DOCX/XLSX/
在當(dāng)今數(shù)字化辦公環(huán)境中,文檔格式的兼容性問題常常給開發(fā)者和終端用戶帶來困擾,本文將介紹如何使用C#高效實(shí)現(xiàn)將ODT、ODS和ODP文件轉(zhuǎn)換為對(duì)應(yīng)的DOCX、XLSX和PPTX格式,需要的可以了解下2026-02-02

