這篇文章給大家介紹在C# 中使用Socke實(shí)現(xiàn)一個(gè)UDP,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

UDP和TCP是網(wǎng)絡(luò)通訊常用的兩個(gè)傳輸協(xié)議,C#一般可以通過Socket來實(shí)現(xiàn)UDP和TCP通訊,由于.NET框架通過UdpClient、TcpListener 、TcpClient這幾個(gè)類對Socket進(jìn)行了封裝,使其使用更加方便, 本文就通過這幾個(gè)封裝過的類講解一下相關(guān)應(yīng)用。
與TCP通信不同,UDP通信是不分服務(wù)端和客戶端的,通信雙方是對等的。為了描述方便,我們把通信雙方稱為發(fā)送方和接收方。
發(fā)送方:
首先創(chuàng)建一個(gè)UDP對象:
string locateIP = "127.0.0.1"; //本機(jī)IP int locatePort = 9001; //發(fā)送端口 IPAddress locateIpAddr = IPAddress.Parse(locateIP); IPEndPoint locatePoint = new IPEndPoint(locateIpAddr, locatePort); UdpClient udpClient = new UdpClient(locatePoint);
發(fā)送數(shù)據(jù):
string remoteIP = "127.0.0.1"; //目標(biāo)機(jī)器IP int remotePort = 9002; //接收端口 IPAddress remoteIpAddr = IPAddress.Parse(remoteIP); IPEndPoint remotePoint = new IPEndPoint(remoteIpAddr, remotePort); byte[] buffer = Encoding.UTF8.GetBytes(“hello”); udpClient.Send(buffer, buffer.Length, remotePoint);
以上就完成了一個(gè)發(fā)送任務(wù),一個(gè)較完整的發(fā)送代碼如下:
public partial class FormServer : Form
{
private UdpClient udpClient = null;
private void btnConnect_Click(object sender, EventArgs e)
{
string locateIP = "127.0.0.1";
int locatePort = 9001;
IPAddress locateIpAddr = IPAddress.Parse(locateIP);
IPEndPoint locatePoint = new IPEndPoint(locateIpAddr, locatePort);
udpClient = new UdpClient(locatePoint);
this.groupWork.Enabled = true;
}
private void Send_Click(object sender, EventArgs e)
{
string text = this.txtSend.Text.Trim();
string remoteIP = "127.0.0.1";
int remotePort = 9002;
byte[] buffer = Encoding.UTF8.GetBytes(text);
if (udpClient != null)
{
IPAddress remoteIp = IPAddress.Parse(remoteIP);
IPEndPoint remotePoint = new IPEndPoint(remoteIp, remotePort);
udpClient.Send(buffer, buffer.Length, remotePoint);
}
Debug.WriteLine("Send OK");
}
}接收端:
首先創(chuàng)建一個(gè)UDP對象:
string locateIP = "127.0.0.1"; int locatePort = 9002; IPAddress locateIpAddr = IPAddress.Parse(locateIP); IPEndPoint locatePoint = new IPEndPoint(locateIpAddr, locatePort); UdpClient udpClient = new UdpClient(locatePoint);
接收數(shù)據(jù):
IPEndPoint remotePoint = new IPEndPoint(IPAddress.Parse("1.1.1.1"), 1);
var received = udpClient.Receive(ref remotePoint);
string info = Encoding.UTF8.GetString(received);
string from=$” {remotePoint.Address}:{remotePoint.Port}”;注意兩點(diǎn):
1、remotePoint是獲得發(fā)送方的IP信息,定義時(shí)可以輸入任何合法的IP和端口信息;
2、Receive方法是阻塞方法,所以需要在新的線程內(nèi)運(yùn)行,程序會一直等待接收數(shù)據(jù),當(dāng)接收到一包數(shù)據(jù)時(shí)程序就返回,要持續(xù)接收數(shù)據(jù)需要重復(fù)調(diào)用Receive方法。
一個(gè)較完整的接收端代碼如下:
public partial class FormClent : Form
{
private UdpClient udpClient = null;
private void btnConnect_Click(object sender, EventArgs e)
{
string locateIP = "127.0.0.1";
int locatePort = 9002;
IPAddress locateIpAddr = IPAddress.Parse(locateIP);
IPEndPoint locatePoint = new IPEndPoint(locateIpAddr, locatePort);
udpClient = new UdpClient(locatePoint);
IPEndPoint remotePoint = new IPEndPoint(IPAddress.Parse("1.1.1.1"), 1);
Task.Run(() =>
{
while (true)
{
if (udpClient != null)
{
var received = udpClient.Receive(ref remotePoint);
string info = Encoding.UTF8.GetString(received);
string from=$” {remotePoint.Address}:{remotePoint.Port}”;
}
}
});
}
}當(dāng)發(fā)送端發(fā)送一包數(shù)據(jù)時(shí),不管對方是否接收都是發(fā)送成功的,UDP協(xié)議本身并不會對發(fā)送的可靠性進(jìn)行驗(yàn)證。(這里的可靠性是指是否接收到,如果對方接收到數(shù)據(jù)包,其內(nèi)容還是可靠的,這個(gè)在鏈路層進(jìn)行了保證。)同時(shí),由于網(wǎng)絡(luò)延時(shí)等因素,先發(fā)送的包并不能確定先被接收到,所以由于這兩個(gè)原因,UDP通信存在丟包和亂序的情況。
某些業(yè)務(wù)場景下,比如實(shí)時(shí)狀態(tài)監(jiān)控,可能對丟包和亂序情況并不敏感, 可以不用處理,但大部分情況下還是介意丟包的,簡單的處理辦法就是把包的頭部固定長度的空間拿出來存放核對信息,比如包編號,如果有缺失,可以要求發(fā)送方重發(fā),也可以進(jìn)行排序。
我們對UdpClent又進(jìn)行一次封裝,啟用一個(gè)線程進(jìn)行接收數(shù)據(jù),將接收到的數(shù)據(jù)包通過事件發(fā)布出來,這樣使用起來就更方便了。
namespace Communication.UDPClient
{
public class UdpStateEventArgs : EventArgs
{
public IPEndPoint remoteEndPoint;
public byte[] buffer = null;
}
public delegate void UDPReceivedEventHandler(UdpStateEventArgs args);
public class UDPClient
{
private UdpClient udpClient;
public event UDPReceivedEventHandler UDPMessageReceived;
public UDPClient(string locateIP, int locatePort)
{
IPAddress locateIp = IPAddress.Parse(locateIP);
IPEndPoint locatePoint = new IPEndPoint(locateIp, locatePort);
udpClient = new UdpClient(locatePoint);
//監(jiān)聽創(chuàng)建好后,創(chuàng)建一個(gè)線程,開始接收信息
Task.Run(() =>
{
while (true)
{
UdpStateEventArgs udpReceiveState = new UdpStateEventArgs();
if (udpClient != null)
{
IPEndPoint remotePoint = new IPEndPoint(IPAddress.Parse("1.1.1.1"), 1);
var received = udpClient.Receive(ref remotePoint);
udpReceiveState.remoteEndPoint = remotePoint;
udpReceiveState.buffer = received;
UDPMessageReceived?.Invoke(udpReceiveState);
}
else
{
break;
}
}
});
}
}
}具體使用辦法:
private void btnConnect_Click(object sender, EventArgs e)
{
string locateIP = "127.0.0.1";
int locatePort = 9002;
UDPClient udpClient = new UDPClient(locateIP, locatePort);
udpClient.UDPMessageReceived += UdpClient_UDPMessageReceived;
}
private void UdpClient_UDPMessageReceived(UdpStateEventArgs args)
{
var remotePoint = args.remoteEndPoint;
string info = Encoding.UTF8.GetString(args.buffer);
}關(guān)于在C# 中使用Socke實(shí)現(xiàn)一個(gè)UDP就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
網(wǎng)頁名稱:在C#中使用Socke實(shí)現(xiàn)一個(gè)UDP-創(chuàng)新互聯(lián)
當(dāng)前鏈接:http://www.chinadenli.net/article42/dccgec.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站導(dǎo)航、自適應(yīng)網(wǎng)站、企業(yè)建站、微信公眾號
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容