C〓〓〓のUDPプロトコルに基づく同期通信実現コード


一、要約
C〓〓のUDPプロトコルに基づく同期通信をまとめます。
 二、実験プラットフォーム
Visual Studio 2010
 三、実験原理
UDP転送プロトコルとTCP転送プロトコルの違いは、関連文書を参照することができます。ここでは説明を省略します。 
四、実例
4.1 socketを採用してUDPを実現する
UDPは無接続のプロトコルですから。したがって、サーバーアプリケーションがUDPパケットを送信し受信できるようにするためには、2つのことが必要です。
(1)オブジェクトを作成します。
(2)作成したソケットオブジェクトを、ローカルIPEndPointと紐付けします。
上記の手順を完了すると、作成されたソケットは、IPEndPoint上で流入したUDPパケットを受信するか、または流出したUDPパケットをネットワーク内の他の任意のデバイスに送信することができる。UDPを使って通信する場合、接続は不要です。異郷ホスト間に接続が確立されていないため、UDPは標準のSend()とReceive()tソケット方法を使用することができず、他の2つの方法を使用しています。
SendTo()メソッドは、送信するデータと、対象機器のIPEndPointを指定します。この方法にはいくつかの異なる使用方法があり、具体的な用途に応じて選択できるが、少なくともパケットと対象機器を指定しなければならない。以下のとおりです

SendTo(byte[] data,EndPoint Remote)
Receive From()方法は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サーバはこのIPEnt Pointにデータを送信します。リモートデバイス上で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} :
{1}
", 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)上記のコードはIPV 6アドレスに基づくマルチキャストモードである。IPv 4におけるブロードキャスト(broadcast)は、ネットワーク性能の低下をもたらし、さらにはブロードキャスト嵐(broadcast storm)を引き起こすことができる。IPv 6には放送という概念が存在せず、代わりにマルチキャストと任意放送(anycast)がある。
(2)IPV 6アドレス表示方法:
a)X:X:X:X:X:X:X(各Xは16ビットの16進数を表します)は、大文字と小文字を区別しません。
b)先頭の0は省略できます。例えば、09 C 0は9 C 0、0000は0と書くことができます。
c)連続して0のフィールドは、以下のようにすることができます。しかし、全体のアドレスの中で:一回だけ現れます。例えば、FF 01:0:0:0:0:0:1でFF 01:1と簡単に書くことができます。
(3)フォームを使用する場合、このようなフォーマットを推奨します。データを受信するとフリーズする可能性があります。

//        

   Thread thread = new Thread(
    delegate()
    {
     try
     {
      //        
     }
     catch (Exception )
     {

     }
    }
   );

   thread.Start();

以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。