c#如何使用UDP進行聊天通信
c#使用UDP進行聊天通信
UDP和TCP都是網(wǎng)絡通信中不可缺少的部分,兩者在不同的環(huán)境中,應用的場景不一樣,UDP在網(wǎng)絡不好的情況下,傳輸會丟包,也就是會丟數(shù)據(jù),而TCP不會這樣,所以重要的數(shù)據(jù)使用TCP傳輸,但是TCP對網(wǎng)絡的資源消耗非常的大,例如視頻,音頻等大量的數(shù)據(jù),這個時候就選擇UDP,因為UDP占用網(wǎng)絡資源比較低,就算丟一幀二幀的圖像的數(shù)據(jù),也不會有影響的。
UDP只管發(fā)送,不管你有沒有接收到信息,比較主動,同理,也會一直接收,只要在線,就能接受對方的信息。UDP比TCP的使用更加的簡單。
UDP通信可以分為使用UDP和UdpClient。UdpClient是Socket的一種封裝。其實UDP通信沒有絕對的服務端和客戶端分別,因為都是連接上,就可以發(fā)送和接收。
使用UDP方式,需要注意發(fā)送消息的IP地址和端口與接收消息的IP地址和端口。
服務端代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//udp 服務端
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
server.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6001));//綁定端口號和IP
Console.WriteLine("服務端已經(jīng)開啟");
Thread t = new Thread(()=>ReciveMsg(server));//開啟接收消息線程
t.Start();
Thread t2 = new Thread(()=>sendMsg(server));//開啟發(fā)送消息線程
t2.Start();
}
static void sendMsg(Socket server)
{
EndPoint point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6000); //向指定的IP和端口發(fā)送消息
while (true)
{
string msg = Console.ReadLine();
server.SendTo(Encoding.UTF8.GetBytes(msg), point);
}
}
static void ReciveMsg(Socket server)
{
while (true)
{
//EndPoint point = new IPEndPoint(IPAddress.Any, 0); //向所有的IP和端口接收消息
EndPoint point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6000); //向指定的IP和端口接收消息
byte[] buffer = new byte[1024];
int length = server.ReceiveFrom(buffer, ref point);//接收數(shù)據(jù)報
string message = Encoding.UTF8.GetString(buffer, 0, length);
Console.WriteLine("收到了消息:" + message);
}
}
}
}客戶端代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6000));
Thread t = new Thread(() => sendMsg(client));
t.Start();
Thread t2 = new Thread(() => ReciveMsg(client));
t2.Start();
Console.WriteLine("客戶端已經(jīng)開啟");
}
static void sendMsg(Socket client)
{
EndPoint point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6001); //向指定的IP和端口發(fā)送消息
while (true)
{
string msg = Console.ReadLine();
client.SendTo(Encoding.UTF8.GetBytes(msg), point);
}
}
static void ReciveMsg(Socket client)
{
while (true)
{
//EndPoint point = new IPEndPoint(IPAddress.Any, 0); //向所有的IP和端口接收消息
EndPoint point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6001); //向指定的IP和端口接收消息
byte[] buffer = new byte[1024];
int length = client.ReceiveFrom(buffer, ref point);//接收數(shù)據(jù)報
string message = Encoding.UTF8.GetString(buffer, 0, length);
Console.WriteLine("收到了消息:" + message);
}
}
}
}效果預覽

使用UdpClient方式,需要注意發(fā)送消息的IP地址和端口與接收消息的IP地址和端口
服務端代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//創(chuàng)建udpclient 綁定ip跟端口號
UdpClient udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8090));
Console.WriteLine("UdpClient服務端已經(jīng)開啟");
Thread t = new Thread(() => ReciveMsg(udpClient));//開啟接收消息線程
t.Start();
Thread t2 = new Thread(() => sendMsg(udpClient));//開啟發(fā)送消息線程
t2.Start();
}
static void sendMsg(UdpClient udpClient)
{
while (true)
{
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);
udpClient.Send(data, data.Length, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8091)); //發(fā)送到指定的IP地址和端口信息
}
}
static void ReciveMsg(UdpClient udpClient)
{
while (true)
{
//接收數(shù)據(jù)
//IPEndPoint point = new IPEndPoint(IPAddress.Any, 0); //接收所有的IP地址和端口信息
IPEndPoint point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8091); //接收指定的IP地址和端口信息
byte[] data = udpClient.Receive(ref point);//
string message = Encoding.UTF8.GetString(data);
Console.WriteLine("收到了消息:" + message);
}
}
}
}客戶端代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
//創(chuàng)建udpclient對象
UdpClient client = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8091));
Console.WriteLine("UdpClient客戶端已經(jīng)開啟");
Thread t = new Thread(() => sendMsg(client));
t.Start();
Thread t2 = new Thread(() => ReciveMsg(client));
t2.Start();
}
static void sendMsg(UdpClient client)
{
while (true)
{
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);
client.Send(data, data.Length, new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8090));
}
}
static void ReciveMsg(UdpClient udpClient)
{
while (true)
{
//接收數(shù)據(jù)
//IPEndPoint point = new IPEndPoint(IPAddress.Any, 0); //接收所有的IP地址和端口信息
IPEndPoint point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8090); //接收指定的IP地址和端口信息
byte[] data = udpClient.Receive(ref point);
string message = Encoding.UTF8.GetString(data);
Console.WriteLine("收到了消息:" + message);
}
}
}
}效果預覽

從以上的案例來看,UDP和UdpClient的區(qū)別基本上都是一樣的,一個使用了Socket 類,一個使用了UdpClient類,然后都是綁定對應的IP地址和端口,然后就是分別調(diào)用Socket類的方法,進行發(fā)送消息和接收消息,調(diào)用UdpClient類的方法,進行發(fā)送消息和接收信息。
其實在新建類的時候,可以不用先進行連接,可以把IP地址和端口,以及消息一次性發(fā)出去。
拓展
單播,廣播,多播三者的區(qū)別
單播
用于兩個主機之間的端對端通信,指定了固定的IP地址和端口,就是一對一的對話,其他人聽不到你們說的話,類似私聊。
代碼:就是上面的代碼,指定了固定的IP地址和端口號,發(fā)送和接收都互相對應。
廣播
用于一個主機對整個局域網(wǎng)上所有主機上的數(shù)據(jù)通信,就是一個人大聲說話,所有的人都能聽到,類似群聊。
代碼:修改成下面2句即可,發(fā)送端和接收端都要修改。
UDP服務端

server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); //Broadcast開啟廣播 EndPoint point = new IPEndPoint(IPAddress.Broadcast, 4567); //開啟廣播,端口是4567
UDP客戶端

EndPoint iep = new IPEndPoint(IPAddress.Any, 4567); //任意ip,端口就是服務端的4567 EndPoint point = new IPEndPoint(IPAddress.Any, 4567); //廣播,端口是4567
UdpClient服務端

UdpClient udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
IPEndPoint point = new IPEndPoint(IPAddress.Broadcast, 4567); //開啟廣播,端口是4567UdpClient客戶端

UdpClient client = new UdpClient(new IPEndPoint(IPAddress.Any, 4567));
IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);多播
介于單播和廣播之間,也叫組播,從名字上面就能知道,建立一個組,然后向組內(nèi)的人員發(fā)送消息,就類似,微信臨時拉一個群,指定群內(nèi)的人,向群內(nèi)通知信息。
代碼:修改成下面2句即可,發(fā)送端和接收端都要修改。
加入多播
udpClient.JoinMulticastGroup(IPAddress.Parse("224.0.0.0"));//將 UdpClient 添加到多播組;IPAddress.Parse將IP地址字符串轉換為IPAddress 實例
IPEndPoint multicast = new IPEndPoint(IPAddress.Parse("224.0.0.0"), 7788); //將網(wǎng)絡終結點表示為 IP 地址和端口號 7788是目的端口退出多播
udpClient.DropMulticastGroup(IPAddress.Parse("224.0.0.0"));//將 UdpClient 從多播組中移除;IPAddress.Parse將IP地址字符串轉換為IPAddress 實例
IPEndPoint multicast = new IPEndPoint(IPAddress.Parse("224.0.0.0"), 7788); //將網(wǎng)絡終結點表示為 IP 地址和端口號 7788是目的端口帶界面操作

代碼
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
CheckForIllegalCrossThreadCalls = false;//在其他線程中可以調(diào)用主窗體控件
}
UdpClient udpClient;
UdpClient client;
private void Form1_Load(object sender, EventArgs e)
{
Thread js = new Thread(() =>
{
client = new UdpClient(new IPEndPoint(IPAddress.Any, 4567));
IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Any, 0);
while (true)
{
try
{
if (client.Available <= 0) continue;
if (client.Client == null) return;
byte[] bytes = client.Receive(ref iPEndPoint);
string str = Encoding.Default.GetString(bytes);
//Invoke(new Action(() => textBox2.Text = str));
textBox2.Text = str;
}
catch (Exception)
{
throw;
}
Thread.Sleep(1000);
}
});
js.Start();
}
private void button1_Click(object sender, EventArgs e)
{
udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
IPEndPoint point = new IPEndPoint(IPAddress.Broadcast, 4567); //開啟廣播,端口是4567
if (textBox1.Text != null)
{
Byte[] sendBytes = Encoding.Default.GetBytes(textBox1.Text);
udpClient.Send(sendBytes, sendBytes.Length, point);
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
udpClient.Dispose();
udpClient.Close();
client.Dispose();
client.Close();
}
}
}總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
c#實現(xiàn)幾種數(shù)據(jù)庫的大數(shù)據(jù)批量插入
這篇文章主要介紹了c#實現(xiàn)幾種數(shù)據(jù)庫的大數(shù)據(jù)批量插入,主要包括SqlServer、Oracle、SQLite和MySQL,有興趣的可以了解一下。2017-01-01

