一、择要
总结基于C#的UDP协定的同步通讯。
二、试验平台
Visual Studio 2010
三、试验道理
UDP传输协定同TCP传输协定的辨别可查阅相干文档,此处不再赘述。
四、实例
4.1 采纳socket完成UDP
由于UDP是一种无衔接的协定。因而,为了使效劳器运用能够发送和吸收UDP数据包,则须要做两件事变:
(1) 竖立一个Socket对象;
(2) 将竖立的套接字对象与当地IPEndPoint举行绑定。
完成上述步骤后,那末竖立的套接字就能够在IPEndPoint上吸收流入的UDP数据包,或许将流出的UDP数据包发送到收集中其他恣意装备。运用UDP举行通讯时,不须要衔接。由于异地的主机之间没有竖立衔接,所以UDP不能运用规范的Send()和Receive()t套接字要领,而是运用两个其他的要领:SendTo()和ReceiveFrom()。
SendTo()要领指定要发送的数据,和目的机械的IPEndPoint。该要领有多种差别的运用要领,能够依据细致的运用举行挑选,然则最少要指定数据包和目的机械。以下:
SendTo(byte[] data,EndPoint Remote)
ReceiveFrom()要领同SendTo()要领相似,然则运用EndPoint对象声明的体式格局不一样。应用ref润饰,通报的不是一个EndPoint对象,而是将参数通报给一个EndPoint对象。
UDP运用不是严厉意义上的真正的效劳器和客户机,而是同等的关联,即没有主与次的关联。为了轻便起见,依然把下面的这个运用叫做UDP效劳器。
效劳器端代码:
using System; using System.Collections.Generic; using System.Text; using System.Net; using System.Net.Sockets; namespace UDP { class Program { static void Main(string[] args) { int recv; byte[] data = new byte[1024]; //获得本机IP,设置TCP端口号 IPEndPoint ip = new IPEndPoint(IPAddress.Any, 8001); Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //绑定收集地点 newsock.Bind(ip); Console.WriteLine("This is a Server, host name is {0}", Dns.GetHostName()); //守候客户机衔接 Console.WriteLine("Waiting for a client"); //获得客户机IP IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); EndPoint Remote = (EndPoint)(sender); recv = newsock.ReceiveFrom(data, ref Remote); Console.WriteLine("Message received from {0}: ", Remote.ToString()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); //客户机衔接胜利后,发送信息 string welcome = "你好 ! "; //字符串与字节数组互相转换 data = Encoding.ASCII.GetBytes(welcome); //发送信息 newsock.SendTo(data, data.Length, SocketFlags.None, Remote); while (true) { data = new byte[1024]; //发送吸收信息 recv = newsock.ReceiveFrom(data, ref Remote); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); newsock.SendTo(data, recv, SocketFlags.None, Remote); } } } }
关于吸收流入的UDP效劳器顺序来讲,必需将顺序与当地体系中指定的UDP端口举行绑定。这就能够经由过程运用适宜的当地IP地点竖立一个IPEndPoint对象,以及适宜的UDP端口号。上述范例顺序中的UDP效劳器能够在端口8001从收集上吸收恣意流入的UDP数据包。
UDP客户机顺序与效劳器顺序异常相似。
由于客户机不须要在指定的UDP端口守候流入的数据,因而,不运用Bind()要领,而是运用在数据发送时体系随机指定的一个UDP端口,而且运用同一个端口吸收返回的音讯。在开发产品时,要为客户机指定一套UDP端口,以便效劳器和客户机顺序运用雷同的端口号。UDP客户机顺序起首定义一个IPEndPoint,UDP效劳器将发送数据包到这个IPEndPoint。如果在长途装备上运转UDP效劳器顺序,在IPEndPoint定义中必需输入恰当的IP地点和UDP端口号信息。
客户端代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; namespace UDPClient { class Program { static void Main(string[] args) { byte[] data = new byte[1024]; string input, stringData; //构建TCP 效劳器 Console.WriteLine("This is a Client, host name is {0}", Dns.GetHostName()); //设置效劳IP,设置TCP端口号 IPEndPoint ip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8001); //定义收集范例,数据衔接范例和收集协定UDP Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); string welcome = "你好! "; data = Encoding.ASCII.GetBytes(welcome); server.SendTo(data, data.Length, SocketFlags.None, ip); IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); EndPoint Remote = (EndPoint)sender; data = new byte[1024]; //关于不存在的IP地点,到场此行代码后,能够在指定时间内消除壅塞情势限定 int recv = server.ReceiveFrom(data, ref Remote); Console.WriteLine("Message received from {0}: ", Remote.ToString()); Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv)); while (true) { input = Console.ReadLine(); if (input == "exit") break; server.SendTo(Encoding.ASCII.GetBytes(input), Remote); data = new byte[1024]; recv = server.ReceiveFrom(data, ref Remote); stringData = Encoding.ASCII.GetString(data, 0, recv); Console.WriteLine(stringData); } Console.WriteLine("Stopping Client."); server.Close(); } } }
上述代码的完成逻辑为:相干设置完成后,效劳器端先向客户端发送信息,以后客户端经由过程键盘发送字符串,效劳器端收到后再发送给客户端,云云轮回。
4.2 采纳UDPClient类完成
效劳器端代码:
using System; using System.Net; using System.Net.Sockets; using System.Text; public class Custom { // 设置IP,IPV6 private static readonly IPAddress GroupAddress = IPAddress.Parse("IP地点"); // 设置端口 private const int GroupPort = 11000; private static void StartListener() { bool done = false; UdpClient listener = new UdpClient(); IPEndPoint groupEP = new IPEndPoint(GroupAddress, GroupPort); try { //IPV6,组播 listener.JoinMulticastGroup(GroupAddress); listener.Connect(groupEP); while (!done) { Console.WriteLine("Waiting for broadcast"); byte[] bytes = listener.Receive(ref groupEP); Console.WriteLine("Received broadcast from {0} :\n {1}\n", groupEP.ToString(), Encoding.ASCII.GetString(bytes, 0, bytes.Length)); } listener.Close(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } public static int Main(String[] args) { StartListener(); return 0; } }
客户端代码:
using System; using System.Net; using System.Net.Sockets; using System.Text; public class Client { private static IPAddress GroupAddress = IPAddress.Parse("IP地点"); private static int GroupPort = 11000; private static void Send(String message) { UdpClient sender = new UdpClient(); IPEndPoint groupEP = new IPEndPoint(GroupAddress, GroupPort); try { Console.WriteLine("Sending datagram : {0}", message); byte[] bytes = Encoding.ASCII.GetBytes(message); sender.Send(bytes, bytes.Length, groupEP); sender.Close(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } public static int Main(String[] args) { Send(args[0]); return 0; } }
以上代码须要申明的是:
(1) 上述代码是基于IPV6地点的组播情势。IPv4中的播送(broadcast)能够致使收集机能的下落以至播送风暴(broadcast storm)。在IPv6中就不存在播送这一概念了,取而代之的是组播(multicast)和恣意播(anycast)。
(2) IPV6地点示意要领:
a) X:X:X:X:X:X:X:X(每一个X代表16位的16进制数字),不辨别大小写;
b) 排头的0可省略,比方09C0就能够写成9C0,0000能够写成0;
c) 一连为0的字段能够以::来替代,然则全部地点中::只能涌现一次,比方FF01:0:0:0:0:0:0:1就能够简写成FF01::1。
(3) 如果是采纳窗体的情势发起运用这类花样,否则在吸收数据时可能会涌现死机的征象。
// 竖立一个子线程 Thread thread = new Thread( delegate() { try { //在这里写你的代码 } catch (Exception ) { } } ); thread.Start();
以上就是详解基于C#的UDP协定的同步通讯的示例代码的细致内容,更多请关注ki4网别的相干文章!