ホームページ > バックエンド開発 > C#.Net チュートリアル > C#のUDPプロトコルによる同期通信のサンプルコードを詳しく解説

C#のUDPプロトコルによる同期通信のサンプルコードを詳しく解説

黄舟
リリース: 2017-03-23 11:38:10
オリジナル
1965 人が閲覧しました

この記事では主に 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 サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート