UDP を介したブロードキャスト要求に対する N 台のクライアントからの応答の受信

StackOverflow https://stackoverflow.com/questions/2364574

質問

特定の種類のネットワーク マルチメディア デバイス用に一種の IP ファインダーを実装しています。LAN 内でそのタイプの生きているすべてのデバイスを、その IP アドレスやその他の詳細情報とともに調べたいと考えています。

デバイスには独自のデバイス検出方法があります。

次のように動作します。クライアントは、UDP 経由で LAN 経由でブロードキャスト要求を送信します。
宛先ポート番号は固定です。
これに応じて、このリクエストの形式を理解する LAN 内のすべてのサーバーがこのリクエストに応答して、自分自身に関する情報を提供します。

sendto() を使用して UDP リクエスト メッセージをブロードキャストしています。

ここで私の問題は、リクエストに応答するデバイス(つまりサーバー)の数がわからないことです。

何回recvfrom()を呼び出す必要がありますか?
すべてのデバイスからの応答を処理したことはいつわかりますか?
それとも一般的に、複数のサーバーから応答を受信するには、recvfrom() が正しい選択なのでしょうか?
同じことを達成するためのより良い(またはここで間違っている場合は正しい)方法はありますか?

私は C/C++ でプログラミングを行っており、Windows と Linux の両方でコードを作成する予定です。
よろしくお願いします。

編集:そこで、ここにあるすべてのネットワーク プログラミング ウィザードの助けを借りて、私の問題の解決策を見つけました:)
select() は私にとってまさに必要なものです...
私を助けるために時間を割いてくださった皆様、本当にありがとうございました

役に立ちましたか?

解決

  

何回)(コールのrecvfromにあるのだろうか?   とき、私は私がすべてのデバイス/サーバからの応答を処理していることを知って来るのだろうか?

あなたはデバイス/サーバの数がわからない場合は、

、あなたがrecvfrom()たりしたときにすべての応答を処理してきたが呼び出す必要がありますどのように多くの時間を知ることができません。

あなたは、データの読み取り可能な状態になったとき(タイムアウトまで)select()ループとコールrecvfrom()を使用して検討するかもしれません。これは、メインスレッドまたは別のスレッドである可能性があります。

データは、それが処理できるよりも早く到着した場合、

は、あなたがデータグラムを失うことになります。これは、データが解析され、それが受信された後に格納されていることを速度に大きく依存します。データを処理する集中操作である場合、それは別のスレッドで処理を行うか、アウトループ回数を受信するまで、データを格納し、それを処理を続行する必要があるかもしれない。

UDPは数回再放送するループ、信頼性がないので、重複を考慮すべき損失との処理の一部のアカウントを助ける必要があります。

次の擬似コードは、私が問題にアプローチする方法をされます:


/* get socket to receive responses */
sd = socket( ... );

do
{
    /* set receive timeout */
    timeout.tv_sec = 5;     

    /* broadcast request */
    sendto( ... );

    /* wait for responses (or timeout) */
    while(select(sd+1, &readfds, NULL, NULL, &timeout) > 0)
    {
        /* receive the response */
        recvfrom( ... );

        /* process the response (or queue for another thread / later processing) */
        ...

        /* reset receive timeout */
        timeout.tv_sec = 5; 
    }

    /* process any response queued for later (and not another thread) */

} while (necessary);
  または一般に、のrecvfrom()複数のサーバからの応答を受信するための正しい選択です?

それは、受信データの送信元アドレスを取得するためにアプリケーションを可能にするので、

recvfrom()は、一般的にコネクションレスモードのソケットで使用されます。

他のヒント

使用タイムアウトあなたは、デバイスからの応答を取得するたびにデクリメントループ内でタイムアウトとselect(2)/poll(2)、。あなたは適切なタイムアウト自分自身を思い付くする必要があると思います。

あなたが発見応答メッセージを解析/認識することができればまた、ちょうどそのようなメッセージを受信すると、リストにデバイスを追加します。

あなたはおそらく、デバイスが登録するときのために、とにかくタイムアウトを扱うが、後の時点で失敗する必要があります。

あなたが応答しようとしているどのように多くのサーバがわからない場合、あなたは(のrecvfromを呼び出す必要が何回か分かりません)。

:私はおそらく完全にテストされていないと愚かなバグのおそらくフルである、適切なタイムアウトと選択()ループ、次のようなもの、とこれを扱うでしょう
/* create and bind socket */

fd_set fds;
struct timeval tv;

tv.tv_sec = 2; 
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(sock, &fds);
int ret;

while((ret = select(sock + 1, &fds, NULL, NULL, &tv)) > 0) {
    char buf[BUFLEN];
    struct sockaddr addr;

    if(recvfrom(sock, buf, BUFLEN, MSG_DONTWAIT, &addr, sizeof(struct sockaddr)) > 0) {
        /* handle response */
    } else {
        /* handle error */
    }        
}
if(ret < 0) {
    /* handle error */
} else {
    /* select() timed out; we're theoretically done */
}

これは何の返事は、それが2秒以上ブロックすることを2秒、当然の手段のために受信されていないまでのrecvfrom()を呼び出し続けます。基本的なプロトコルに応じて、あなたはおそらくはるかに短いタイムアウトで逃げることができます。確かにあなたは各応答でそれを減らすことができます。いくつかのテストとチューニングを最適な構成を見つけることが必要になります。あなたが同時に応答サーバを心配する必要はありません。イーサネット層はそれを処理します。

それを知ることはできません。それは不可知です。

あなたの説明から推測すると、次のようになります。 I want to find out all the alive devices, 、デバイスは、必要に応じていつでも、死んだ状態から生きた状態に移行し、再び元の状態に戻ることができます。これは、継続的にポーリングする必要があることを意味します。つまり、数秒ごとにブロードキャストリクエストを送信し(あまり頻繁ではありません)、誰が応答するかを確認します。

UDP は本質的に信頼性が低いという私の考えが正しければ、UDP の上に信頼性を後付けする必要があります。

  • デバイスは毎回ブロードキャストを受信できない可能性があるため、数秒ごとにブロードキャストを送信します。
  • 返信は受け取れないかもしれませんが、次回は受け取れるかもしれません。
  • 応答により、デバイスが生きていることが確認されます。
  • デバイスが停止していると宣言する前に、「n」回の無応答を待ちます。

可能なデバイスの最大数を知っていますか?その場合、recvfrom() を何回も呼び出す必要があることがわかります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top