2

こんにちは、ネットワーク クラスのプロジェクトに取り組んでいます。このプロジェクトでは、udp 経由で制御アプリからメッセージを受信し、他のノードとの tcp 接続を作成するノードをネットワーク内に作成しています。基本的な順序は次のとおりです。 1) コントロール マネージャがノード A に udp メッセージを送信し、ノード B に接続するように指示する 2) ノード A が udp メッセージを受信し、その udp メッセージをノード B に転送する 3) ノード B が udp メッセージを受信し、ランダムにポートを選択する4) ノード A は udp メッセージを受信し、その TCP ポートでノード B への接続を開きます。

基本的に、受信した udp メッセージをループし、メッセージ解析関数にジャンプすると同時に、tcp 接続をループしたいと考えています。その部分は単純に思えますが、リスニング ソケットをファイル記述子リストに追加する方法がよくわかりません。次のコードは私がまとめたもので、基本的な構造が正しいかどうか疑問に思っていますか? リッスンする tcp ソケットを作成して fd リストに追加する方法がよくわかりません。

SOCKET udpsock;
udpsock = initudp(port); //setup udp socket
SOCKET tcpsock;
FD_ZERO(&rdsocks);

max = udpsock + 1;
while(1)
{
    SOCKET temp;

    FD_SET(udpsock,&rdsocks);//setup udp macros
    FD_SET(tcpsock,&rdsocks);

    if( select(max,&rdsocks,NULL,NULL,NULL) == SOCKET_ERROR )
    {
        perror("Select error");
        WSACleanup();
        return 1;
    }
    for(temp = 0; temp<=max;temp++) // loop on TCP sockets
    {
        if(FD_ISSET(temp,&rdsocks))
        {
            printf("Socket %d is ready \n",temp);
            // process tcp messages
        }

    }
    if(FD_ISSET(udpsock,&rdsocks)) // udp connection, parse control message
    {
        int ret = 0;
        res = recvfrom(udpsock, buff,sizeof(buff),0,(struct sockaddr*)&udpclient,lenaddr);
        //process udp message, setup tcp connection here if requested and add to file descriptor list?
    }

}
4

2 に答える 2

2

socket(2)リッスンする TCP ソケット ( 、bind(2)、 )を作成したらlisten(2)、 で非ブロッキングとしてマークしsetsockopt(2)、 の読み取りセットに追加しselect(2)ます。

「読み取り可能」になると、クライアント接続が保留中であることを意味し、 を呼び出しますaccept(2)。新しく接続されたソケットも読み取りセットに追加します。

これらのクライアントソケットのリスト/ハッシュ/何でも保持したい場合があります。これは、各呼び出しの前に read-set を再初期化しselect(2)、その最初の引数 (最大 fd) を計算する必要があるためです。

注 0: ここでは Linux のマニュアル ページを参照しますが、ロジックはほぼクロスプラットフォームです。MSDNで Windows のリファレンスを見つけることができます。 注 1: Windowsselect()は最初の引数を無視します。

于 2012-12-05T20:18:14.037 に答える
1

andFD_ZERO()を呼び出す前に、各ループ反復を呼び出す必要があります。また、最初に接続を試みるまで、TCPソケットをに追加しないでください。作成したTCPソケットのリストを保持して、ループの反復ごとにそれらを再度追加できるようにします。FD_SET()select()fd_setfd_set

次のようなものを試してください。

udpsock = initudp(port); //setup udp socket

std::vector<SOCKET> tcpsocks;
SOCKET tcpsock;

while(1)
{
    FD_ZERO(&rdsocks);
    FD_SET(udpsock, &rdsocks);
    max = udpsock;

    for(size_t i = 0; i < tcpsocks.size(); ++i)
    {
        tcpsock = tcpsocks[i];
        FD_SET(tcpsock, &rdsocks);

        if( tcpsock > udpsock )
            max = tcpsock;
    }

    if( select(max+1, &rdsocks, NULL, NULL, NULL) == SOCKET_ERROR )
    {
        perror("Select error");
        WSACleanup();
        return 1;
    }

    for(size_t i = 0; i < tcpsocks.size(); ++i) // loop on TCP sockets
    {
        tcpsock = tcpsocks[i];            
        if( FD_ISSET(tcpsock, &rdsocks) )
        {
            printf("Socket %d is ready \n", tcpsock);
            // process tcp message
        }
    }

    if( FD_ISSET(udpsock, &rdsocks) )
    {
        int ret = 0;
        res = recvfrom(udpsock, buff, sizeof(buff), 0, (struct sockaddr*)&udpclient, lenaddr);
        // process udp message...
        if( setup tcp connection is requested )
        {
            tcpsock = ...;
            if( tcpsock != INVALID_SOCKET )
                tcpsocks.push_back(tcpsock);
        }
    }
}
于 2012-12-06T02:01:55.557 に答える