0

概要:サーバーとクライアントをセットアップしました。どちらも UDP を使用して互いの検出を試みます。サーバーが起動すると、サーバーは稼働中であることを示すマルチキャスト メッセージ (239.1.1.1) を送信します。クライアントが起動すると、クライアントは自分が生きていることを示すマルチキャスト メッセージ (239.1.1.2) を送信します。サーバーとクライアントの両方が、互いのマルチキャスト メッセージにサブスクライブして、送信を受信します。このようにして、どちらのアプリケーション (サーバーまたはクライアント) が最初に起動するかに関係なく、どちらか一方にその存在が通知されます。

クライアント側では、次のことを行います。

  1. サーバーから発信されたマルチキャスト メッセージをサブスクライブして受信するために、リッスン ソケットを設定します。

  2. 以下の #3 に従って、クライアントのマルチキャスト メッセージに対するサーバー応答を受信する受信ソケットをセットアップします。
  3. クライアントが実行しているマルチキャスト メッセージを (サーバーが受信して応答するように) 送信します。
  4. #3 で送信されたクライアントのマルチキャスト メッセージに対するサーバーの応答を受信します。

質問:両方の受信ソケットがサーバーの (非マルチキャスト) 応答をクライアントに取得することを除いて、すべて正常に動作しています。これが予想される動作かどうかはわかりません。2 つの受信ソケットを 1 つに減らすことはできますか? #1 はサーバーのマルチキャストにサブスクライブし、#2 は同じポートでサーバーからの直接送信 (サーバーからの非マルチキャスト メッセージ) をリッスンするだけです。2 番目の受信ソケットを安全に取り外すことができますか?

以下のソース コードを参照してください (コード表示を簡略化するために例外処理を削除しました)。

クライアントコード:

// 1. Set up a socket and asynchronously listen for server startup multicasts.
Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
    ProtocolType.Udp);
listenSocket.SetSocketOption(SocketOptionLevel.Socket,
    SocketOptionName.ReuseAddress, 1);
listenSocket.Bind(new IPEndPoint(IPAddress.Any, 50000));
listenSocket.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.AddMembership,
    new MulticastOption(IPAddress.Parse("239.1.1.1")));
EndPoint clientEndPoint = new IPEndPoint(0, 0);
listenSocket.BeginReceiveFrom(receiveBuffer, 0, receiveBuffer.Length,
    SocketFlags.None, ref clientEndPoint,
    new AsyncCallback(OnServerMessageReceived), (object)this);

// 2. Set up socket to receive the server's response to client's multicast.
Socket receiveSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
    ProtocolType.Udp);
receiveSocket.SetSocketOption(SocketOptionLevel.Socket,
    SocketOptionName.ReuseAddress, 1);
receiveSocket.Bind(new IPEndPoint(IPAddress.Any, 50000));
receiveSocket.ReceiveTimeout = 3000; // Timeout after 3 seconds.

// 3. Send a multicast message for server to respond to.
Socket sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
    ProtocolType.Udp);
EndPoint multicastEndPoint = new IPEndPoint(IPAddress.Parse("239.1.1.2"), 50000);
sendSocket.SendTo(packet, packet.Length, SocketFlags.None, multicastEndPoint);

// 4. Wait for server to respond to the multicast message (timeout = 3 seconds).
byte[] receiveBuff = new byte[2048];
EndPoint serverEndPoint = new IPEndPoint(0, 0);
int bytesRead = receiveSocket.ReceiveFrom(receiveBuff, ref serverEndPoint);

サーバーコード:

// Receive multicast message sent from client (in asynchronous callback method).
EndPoint clientEndPoint = new IPEndPoint(0, 0);
int bytesRead = listenSocket.EndReceiveFrom(asyncResult, ref clientEndPoint);

// Send response back to the client (change port to 50000).
EndPoint destination = new IPEndPoint((clientEndPoint as IPEndPoint).Address,
    50000);
Socket responseSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
    ProtocolType.Udp);
responseSocket.SendTo(response, response.Length, SocketFlags.None, destination);
4

4 に答える 4

4

あなたの質問に対する答えは、「はい、これは予想される動作です」です。同じポートでユニキャスト パケットを受信するために別のソケットを開く必要はありません。

PS

新しいクライアントをリッスンするためにサーバーをマルチキャスト グループに参加させるのはやり過ぎのように思えます。サーバーに「私はここにいます」というビーコンをクライアントのマルチキャスト アドレスに定期的に送信させることもできます (たとえば、30 秒ごとに 1 回)。

于 2009-07-29T07:36:35.297 に答える
2
receiveSocket.Bind(new IPEndPoint(IPAddress.Any, 50000));

受信ソケットは任意のアドレスにバインドされます。つまり、ユニキャスト、ブロードキャスト、およびマルチキャスト トラフィックを受信します。インターフェイス アドレスにバインドしてユニキャスト トラフィックのみを受信することも、マルチキャスト グループのみにバインドしてマルチキャスト トラフィックのみを受信することもできます。

UDP データグラムを送信する場合、マルチキャストまたはユニキャストの宛先アドレスを指定できます。したがって、サーバー コードとクライアント コードの両方をそれぞれ 1 つのソケットに減らすことができます。

于 2010-02-06T04:55:39.823 に答える
0

問題に対処しているかどうかはわかりませんが、クライアントとサーバーの両方が同じIP マルチキャスト アドレス (239.1.1.1 など) で通信することを期待しています。現時点では、クライアントとサーバーにそれぞれ 1 つのアドレスを指定したようですが、新しいクライアントを導入するとどうなりますか?

于 2009-07-21T15:46:17.583 に答える
0

BonjourAvahiなどのサービス ディスカバリ プロトコルを使用する方が、独自に開発するよりも優れています。これらのプロトコルはすでに多くの問題を解決しています。

于 2009-07-29T07:49:16.520 に答える