开发者

Socket transmit data but can't receive response

I am trying to implement UpNP in C++, I found a few sources on google but none worked. I found this one working (http://www.codeproject.com/KB/IP/upnplib.aspx) but it's for .NET, so I decided to sniff the network to see what the code was doing and then do the same with sockets.

Here are the results (full size: http://i.stack.imgur.com/eLoHK.jpg):

Socket transmit data but can't receive response

That shows me that the packet doesn't look bad, everything seems to be the same, everything but the source address of my code, which I don't know how to control (both my code and finder.net.exe are being tested on the same computer connected to the same network).

Here's my code:

#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 =开发者_JS百科 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;
}

I removed all the WSAGetLastError() error checking to make the code easier to read, everything goes fine until recvfrom, that always returns -1 and strerror(WSAGetLastError()) prints "Unknown error".

I hope someone could guide me in the right direction, I've been the last two days trying to make this work.


Why broadcast? UPnP uses multicast, so as far as I remember (Unix) you should use setsockopt() to request that the kernel join a multicast group. I am not sure about Windows, it could be the same call. Something like:

 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))


EDIT:

As hasturkun pointed out, my initial answer was wrong. Also, slemdx correctly diagnosed the problem: the uPnP request is going out from the wrong interface. The problem is, I am not sure how you can determine the right interface. One possibility is to use the interface containing the default gateway on the routing table, but I don't think that would be the right choice. There may be uPnP devices hooked to other interfaces.

One option is to send the initial search packet on all available interfaces. Maybe the answers to this question can help. There is also another link on the last answer that you should check out.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜