如何正确地重复使用套接字选项

时间:2013-11-15 19:49:14

标签: c sockets winsock setsockopt

我现在正在调试我的套接字应用程序,包括运行和持续关闭它。我的问题是当我运行并关闭它然后再次运行它我收到10048错误代码,指示已经在使用的地址。我尝试将套接字描述符设置为SO_REUSEADDR,但如果我一直运行并关闭我的应用程序,仍然会收到10048错误代码。

int getExternalpAddress(char *upnpDeviceIp, char *localIp, char *externalIpAddress) {
    WSADATA wsaData;
    struct sockaddr_in upnpControl, 
                       upnpDevice;
    int i = 0,
        j = 0,
        result = -1,
        bodyLen = 0;
    char c, 
         *tmp = NULL,
         *pLen = NULL,
         *bodyResponse = NULL,
         pBodyLen[5], 
         responseHeader[512],
         getExternalIpRequest[622]; 
    int reuseAddress = 1;

    ZeroMemory(getExternalIpRequest, 622);
    StringCbPrintf(getExternalIpRequest, 622,
                                             "POST /UD/?3 HTTP/1.1\r\n"
                                             "Content-Type: text/xml; charset=\"utf-8\"\r\n" 
                                             "SOAPAction: \"urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress\"\r\n"
                                             "User-Agent: Mozilla/4.0 (compatible; UPnP/1.0; Windows 9x)\r\n"
                                             "Host: %s\r\n"
                                             "Content-Length: 303\r\n"
                                             "Connection: Close\r\n"
                                             "Cache-Control: no-cache\r\n"
                                             "Pragma: no-cache\r\n\r\n"
                                             "<?xml version=\"1.0\"?>"
                                             "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
                                             "<SOAP-ENV:Body>"
                                             "<m:GetExternalIPAddress xmlns:m=\"urn:schemas-upnp-org:service:WANIPConnection:1\"/>"
                                             "</SOAP-ENV:Body>"
                                             "</SOAP-ENV:Envelope>\r\n\r\n", upnpDeviceIp);
    result = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if(result != 0)
        return WSAGetLastError();

    SOCKET sock = INVALID_SOCKET;
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock == SOCKET_ERROR)
        return WSAGetLastError();

    if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseAddress, sizeof(reuseAddress)))
        return WSAGetLastError();

    ZeroMemory(&upnpControl, sizeof(upnpControl));
    upnpControl.sin_family = AF_INET;
    if(localIp == NULL)
        upnpControl.sin_addr.s_addr = INADDR_ANY;
    else
        upnpControl.sin_addr.s_addr = inet_addr(localIp);

    upnpControl.sin_port = htons(8000);
    if(bind(sock, (struct sockaddr *)&upnpControl, sizeof(struct sockaddr)) == SOCKET_ERROR)
        return WSAGetLastError();

    ZeroMemory(&upnpDevice, sizeof(upnpDevice));
    upnpDevice.sin_family = AF_INET;
    upnpDevice.sin_port = htons(80);
    upnpDevice.sin_addr.s_addr = inet_addr(upnpDeviceIp);
    if(connect(sock, (struct sockaddr *)&upnpDevice, sizeof(struct sockaddr)) == SOCKET_ERROR)
        return WSAGetLastError();

    result = send(sock, getExternalIpRequest, lstrlen(getExternalIpRequest), 0);
    if(result != lstrlen(getExternalIpRequest))
        return WSAGetLastError();

    ZeroMemory(responseHeader, 512);
    while(recv(sock, &c, 1, 0) > 0) {
        responseHeader[i] = c;
        if(strstr(responseHeader, "\r\n\r\n")) {
            // Move the pointer to the first digit
            pLen = strstr(responseHeader, "Content-Length: ") + 16;
            ZeroMemory(pBodyLen, 5);
            // Get the body length
            while(*pLen != '\r') {
                pBodyLen[j] = *pLen;
                *pLen++;
                ++j;
            }

            bodyLen = atoi(pBodyLen);
            j = 0;
            bodyResponse = (char *)MALLOC(bodyLen);
            while(recv(sock, &c, 1, 0) > 0) {
                bodyResponse[j] = c;
                ++j;

                if(j == bodyLen) { // We got the HTTP body
                    closesocket(sock);
                }
            }
        }

        ++i;
    }

    i = 0;
    tmp = strstr(bodyResponse, "<NewExternalIPAddress>") + 22;
    ZeroMemory(externalIpAddress, 16);
    while(*tmp != '<') {
        externalIpAddress[i] = *tmp;
        *tmp++;
        ++i;
    }

    FREE(bodyResponse);
    WSACleanup();
    return 0;
}

0 个答案:

没有答案