国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

基于C#的UDP協(xié)議的同步通信實(shí)現(xiàn)代碼

2019-10-29 21:14:24
字體:
供稿:網(wǎng)友

一、摘要

總結(jié)基于C#的UDP協(xié)議的同步通信。

 二、實(shí)驗(yàn)平臺

Visual Studio 2010

 三、實(shí)驗(yàn)原理

UDP傳輸協(xié)議同TCP傳輸協(xié)議的區(qū)別可查閱相關(guān)文檔,此處不再贅述。 

四、實(shí)例

4.1 采用socket實(shí)現(xiàn)UDP

由于UDP是一種無連接的協(xié)議。因此,為了使服務(wù)器應(yīng)用能夠發(fā)送和接收UDP數(shù)據(jù)包,則需要做兩件事情:

(1) 創(chuàng)建一個Socket對象;

(2) 將創(chuàng)建的套接字對象與本地IPEndPoint進(jìn)行綁定。

完成上述步驟后,那么創(chuàng)建的套接字就能夠在IPEndPoint上接收流入的UDP數(shù)據(jù)包,或者將流出的UDP數(shù)據(jù)包發(fā)送到網(wǎng)絡(luò)中其他任意設(shè)備。使用UDP進(jìn)行通信時,不需要連接。因?yàn)楫惖氐闹鳈C(jī)之間沒有建立連接,所以UDP不能使用標(biāo)準(zhǔn)的Send()和Receive()t套接字方法,而是使用兩個其他的方法:SendTo()和ReceiveFrom()。

SendTo()方法指定要發(fā)送的數(shù)據(jù),和目標(biāo)機(jī)器的IPEndPoint。該方法有多種不同的使用方法,可以根據(jù)具體的應(yīng)用進(jìn)行選擇,但是至少要指定數(shù)據(jù)包和目標(biāo)機(jī)器。如下:

SendTo(byte[] data,EndPoint Remote)

ReceiveFrom()方法同SendTo()方法類似,但是使用EndPoint對象聲明的方式不一樣。利用ref修飾,傳遞的不是一個EndPoint對象,而是將參數(shù)傳遞給一個EndPoint對象。

UDP應(yīng)用不是嚴(yán)格意義上的真正的服務(wù)器和客戶機(jī),而是平等的關(guān)系,即沒有主與次的關(guān)系。為了簡便起見,仍然把下面的這個應(yīng)用叫做UDP服務(wù)器。

服務(wù)器端代碼:

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];   //得到本機(jī)IP,設(shè)置TCP端口號      IPEndPoint ip = new IPEndPoint(IPAddress.Any, 8001);   Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);   //綁定網(wǎng)絡(luò)地址   newsock.Bind(ip);   Console.WriteLine("This is a Server, host name is {0}", Dns.GetHostName());   //等待客戶機(jī)連接   Console.WriteLine("Waiting for a client");   //得到客戶機(jī)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));   //客戶機(jī)連接成功后,發(fā)送信息   string welcome = "你好 ! ";   //字符串與字節(jié)數(shù)組相互轉(zhuǎn)換   data = Encoding.ASCII.GetBytes(welcome);   //發(fā)送信息   newsock.SendTo(data, data.Length, SocketFlags.None, Remote);   while (true)   {    data = new byte[1024];    //發(fā)送接收信息    recv = newsock.ReceiveFrom(data, ref Remote);    Console.WriteLine(Encoding.ASCII.GetString(data, 0, recv));    newsock.SendTo(data, recv, SocketFlags.None, Remote);   }  } }}

對于接收流入的UDP服務(wù)器程序來說,必須將程序與本地系統(tǒng)中指定的UDP端口進(jìn)行綁定。這就可以通過使用合適的本地IP地址創(chuàng)建一個IPEndPoint對象,以及合適的UDP端口號。上述范例程序中的UDP服務(wù)器能夠在端口8001從網(wǎng)絡(luò)上接收任意流入的UDP數(shù)據(jù)包。

UDP客戶機(jī)程序與服務(wù)器程序非常類似。

因?yàn)榭蛻魴C(jī)不需要在指定的UDP端口等待流入的數(shù)據(jù),因此,不使用Bind()方法,而是使用在數(shù)據(jù)發(fā)送時系統(tǒng)隨機(jī)指定的一個UDP端口,而且使用同一個端口接收返回的消息。在開發(fā)產(chǎn)品時,要為客戶機(jī)指定一套UDP端口,以便服務(wù)器和客戶機(jī)程序使用相同的端口號。UDP客戶機(jī)程序首先定義一個IPEndPoint,UDP服務(wù)器將發(fā)送數(shù)據(jù)包到這個IPEndPoint。如果在遠(yuǎn)程設(shè)備上運(yùn)行UDP服務(wù)器程序,在IPEndPoint定義中必須輸入適當(dāng)?shù)腎P地址和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;   //構(gòu)建TCP 服務(wù)器   Console.WriteLine("This is a Client, host name is {0}", Dns.GetHostName());   //設(shè)置服務(wù)IP,設(shè)置TCP端口號   IPEndPoint ip = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8001);   //定義網(wǎng)絡(luò)類型,數(shù)據(jù)連接類型和網(wǎng)絡(luò)協(xié)議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地址,加入此行代碼后,可以在指定時間內(nèi)解除阻塞模式限制   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();  } }}

上述代碼的實(shí)現(xiàn)邏輯為:相關(guān)設(shè)置完成后,服務(wù)器端先向客戶端發(fā)送信息,之后客戶端通過鍵盤發(fā)送字符串,服務(wù)器端收到后再發(fā)送給客戶端,如此循環(huán)。

4.2 采用UDPClient類實(shí)現(xiàn)

服務(wù)器端代碼:

using System;using System.Net;using System.Net.Sockets;using System.Text;public class Custom{ // 設(shè)置IP,IPV6 private static readonly IPAddress GroupAddress = IPAddress.Parse("IP地址"); // 設(shè)置端口 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)可以導(dǎo)致網(wǎng)絡(luò)性能的下降甚至廣播風(fēng)暴(broadcast storm)。在IPv6中就不存在廣播這一概念了,取而代之的是組播(multicast)和任意播(anycast)。

(2) IPV6地址表示方法:

a) X:X:X:X:X:X:X:X(每個X代表16位的16進(jìn)制數(shù)字),不區(qū)分大小寫;

b) 排頭的0可省略,比如09C0就可以寫成9C0,0000可以寫成0;

c) 連續(xù)為0的字段可以以::來代替,但是整個地址中::只能出現(xiàn)一次,比如FF01:0:0:0:0:0:0:1就可以簡寫成FF01::1。

(3) 如果是采用窗體的形式建議使用這種格式,否則在接收數(shù)據(jù)時可能會出現(xiàn)死機(jī)的現(xiàn)象。

// 創(chuàng)建一個子線程   Thread thread = new Thread(    delegate()    {     try     {      //在這里寫你的代碼     }     catch (Exception )     {     }    }   );   thread.Start();

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識閱讀請移步到c#教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 奇台县| 河曲县| 遂溪县| 万荣县| 乌鲁木齐市| 金堂县| 大埔县| 南漳县| 紫阳县| 韶关市| 沅陵县| 津南区| 建湖县| 平乡县| 吉安县| 金塔县| 延庆县| 怀来县| 托克逊县| 建昌县| 额尔古纳市| 信阳市| 得荣县| 清新县| 宁蒗| 宾川县| 永康市| 梓潼县| 板桥市| 涟水县| 新蔡县| 江安县| 军事| 永清县| 呼图壁县| 长阳| 内黄县| 西安市| 博罗县| 仲巴县| 杭锦旗|