この記事では主に C# をベースにした UDP プロトコルの同期実装コードを紹介していますが、編集者が非常に良いと思ったので、参考として共有させていただきます。エディターをフォローして見てみましょう
1. まとめ
C# ベースの UDP プロトコルの同期通信をまとめます。
2. 実験プラットフォーム
Visual Studio 2010
3. 実験原理
UDP 送信プロトコルと TCP 送信プロトコルの違いは関連ドキュメントに記載されているため、ここでは説明しません。
IV. 例
4.1 ソケットを使用して UDP を実装する
UDP はコネクションレス型プロトコルであるためです。したがって、サーバー アプリケーションが UDP パケットを送受信するには、次の 2 つのことを行う必要があります:
(1) Socket オブジェクトを作成する;
(2) 作成された Socket オブジェクトをローカル IPEndPoint にバインドする。
上記の手順を完了すると、作成されたソケットは IPEndPoint で受信 UDP データ パケットを受信したり、ネットワーク内の他のデバイスに送信 UDP データ パケットを送信したりできます。 UDP を使用して通信する場合、接続は必要ありません。リモート ホスト間に接続が確立されていないため、UDP は標準の Send() および Receive()t ソケット メソッドを使用できませんが、他の 2 つのメソッド、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 アドレスと適切な UDP ポート番号を使用して IPEndPoint オブジェクトを作成することによって実現されます。上記のプログラム例の UDP サーバーは、ネットワークからポート 8001 で受信する UDP パケットを受信できます。
UDP クライアント プログラムはサーバー プログラムと非常によく似ています。
クライアントは指定された UDP ポートで受信データを待つ必要がないため、Bind() メソッドは使用されませんが、データの送信時にシステムによってランダムに指定された UDP ポートと同じポートが使用されます。返された情報を受け取るために使用されます。製品を開発するときは、サーバー プログラムとクライアント プログラムが同じポート番号を使用するように、クライアントの UDP ポートのセットを指定します。 UDP クライアント プログラムは最初に IPEndPoint を定義し、UDP サーバーはこの IPEndPoint にデータ パケットを送信します。リモート デバイス上で UDP サーバー プログラムを実行している場合は、適切な IP アドレスと UDP ポート番号の情報を IPEndPoint 定義に入力する必要があります。
クライアントコード:
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 でのブロードキャストは、ネットワーク パフォーマンスの低下やブロードキャスト ストームを引き起こす可能性があります。ブロードキャストの概念は IPv6 には存在せず、マルチキャストとエニーキャストに置き換えられます。
(2) IPV6 アドレス表現方法:
a) X:X:X:X:X:X:X:X (各 X は 16 桁の 16 進数を表します)、大文字と小文字は区別されません
b)先頭の 0 は省略できます。たとえば、09C0 は 9C0 として記述でき、0000 は 0 として記述できます。
c) 連続した 0 を持つフィールドは :: で置き換えることができますが、:: はアドレス全体で 1 回のみ使用できます。 FF01: 0:0:0:0:0:0:1 などは、FF01::1 と省略できます。
(3) フォーム形式の場合は、この形式を使用することをお勧めします。そうしないと、データ受信時にクラッシュする可能性があります。
りー以上がC#のUDPプロトコルによる同期通信のサンプルコードを詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。