1

私はC++でUpNPを実装しようとしていますが、グーグルでいくつかのソースを見つけましたが、どれも機能しませんでした。これは機能していることがわかりました(http://www.codeproject.com/KB/IP/upnplib.aspx)が、.NET用であるため、ネットワークをスニッフィングしてコードの動作を確認し、同じことを行うことにしました。ソケット。

結果は次のとおりです(フルサイズ:http://i.stack.imgur.com/eLoHK.jpg): ここに画像の説明を入力してください

これは、パケットが悪く見えないことを示しています。すべてが同じように見えます。コードの送信元アドレスを除いて、制御方法がわかりません(コードとfinder.net.exeの両方がテストされています)。同じネットワークに接続された同じコンピュータ上)。

これが私のコードです:

#define upnp_broadcast_ip   "239.255.255.250"
#define upnp_broadcast_port 1900
#define upnp_search_request "M-SEARCH * HTTP/1.1\r\n"       \
                            "Host:239.255.255.250:1900\r\n" \
                            "ST:upnp:rootdevice\r\n"        \
                            "Man:\"ssdp:discover\"\r\n"     \
                            "MX:3\r\n"                      \
                            "\r\n"

WSAStartup(MAKEWORD(2, 2), &WsaData);

BOOL discover( )
{
    SOCKET              ConnectSocket;
    struct sockaddr_in  Addr;
    char                Buffer[1450];
    int                 t       = 0,
                        iResult = 0,
                        TrueLen = sizeof(bool);
    bool                True    = true;
    ulong               One     = 1;

    // Open datagram socket
    ConnectSocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );

    // Clear out struct
    memset( &Addr, 0, sizeof(Addr) );

    // Specify the address family, IP address, and port
    Addr.sin_family      = AF_INET;
    Addr.sin_port        = htons( upnp_broadcast_port );
    Addr.sin_addr.s_addr = inet_addr( upnp_broadcast_ip );

    iResult = setsockopt( ConnectSocket, SOL_SOCKET, SO_BROADCAST, (char*)&True, TrueLen ); // Not sure what is this for

    // Transmit data
    int sent = sendto( ConnectSocket, upnp_search_request, strlen(upnp_search_request), 0, (struct sockaddr*)&Addr, sizeof(Addr) );

    // Try to receive data 10 times
    for( t = 0; t < 10; t++ )
    {
        ioctlsocket( ConnectSocket, FIONBIO, &One );

        // Clear out buffer
        memset( &Buffer, 0, sizeof(Buffer) );
        int length = sizeof(Addr);

        // Receive data
        iResult = recvfrom( ConnectSocket, Buffer, (sizeof(Buffer) - 1), 0, (struct sockaddr*)&Addr, &length );
        if( iResult == SOCKET_ERROR)
        {
            Sleep( 1000 );
            continue;
        } else {
            // Do stuff with received data
        }
    }

    closesocket( ConnectSocket );
    return FALSE;
}

コードを読みやすくするために、すべてのWSAGetLastError()エラーチェックを削除しました。recvfromまではすべて正常に実行され、常に-1が返され、strerror(WSAGetLastError())は「不明なエラー」を出力します。

誰かが私を正しい方向に導いてくれることを願っています。私はこの2日間、この仕事をしようとしてきました。

4

2 に答える 2

2

なぜ放送するのですか?UPnPはマルチキャストを使用します。私が覚えている限り(Unix)、setsockopt()を使用して、カーネルがマルチキャストグループに参加するように要求する必要があります。Windowsについてはよくわかりませんが、同じ呼び出しである可能性があります。何かのようなもの:

 struct ip_mreq mreq;
 ....
 mreq.imr_multiaddr.s_addr=inet_addr(GROUP_IP);
 mreq.imr_interface.s_addr=htonl(INADDR_ANY);

 setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq))
于 2011-05-19T08:02:59.697 に答える
1

編集:

hasturkunが指摘したように、私の最初の答えは間違っていました。また、slemdxは問題を正しく診断しました:uPnPリクエストが間違ったインターフェースから送信されています。問題は、適切なインターフェースをどのように決定できるかわからないことです。1つの可能性は、ルーティングテーブルのデフォルトゲートウェイを含むインターフェイスを使用することですが、それは正しい選択ではないと思います。他のインターフェイスに接続されたuPnPデバイスが存在する可能性があります。

1つのオプションは、使用可能なすべてのインターフェイスで初期検索パケットを送信することです。たぶん、この質問への答えが役立つかもしれません。最後の回答には、チェックアウトする必要のある別のリンクもあります。

于 2011-05-18T21:55:53.423 に答える