如果多个线程正在运行,Winsock Connect调用会崩溃,那么在一个线程中工作正常吗?

时间:2018-12-20 18:14:18

标签: c++ multithreading winsock2

我有一个需要下载可变文件列表的应用程序(基于用户的更改,更改的内容等)。列表可以很短也可以很长(1000个文件)。我以要下载的每个线程的列表开始X工作者线程。如果我运行1个线程,则一切正常。如果我运行的线程数大于1,它将“可能”在__acrt_lock中崩溃(但是我不称其为)。问题出在winsock连接呼叫上。如果我将该通话注释掉,它将可以正常工作(显然不会下载文件,但不会崩溃)。

这是在旧的v110编译器链下使用的。我已经升级到v141链,现在出现了问题。当然,我正在使用多线程库。

我在不同的地方用过早的return语句“简化”了代码,并确定调用winsock函数“ connect”的一行是问题所在。没有使用全局变量(只有线程的私有本地存储)。

bool Socket::connect(const char * adrs, int port) {

    lastErrCode = 0;
    myIP = adrs;
    myPort = port;

    if (inet_addr(adrs) == INADDR_NONE) {
        getHostByName(adrs, myIP);
    }
    else {
        myIP = adrs;
    }

    if ((me = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
        lastErrCode = WSAGetLastError();
        return (false);
    }

    SOCKADDR_IN sock;
    sock.sin_family = PF_INET;
    sock.sin_port = htons(port);
    sock.sin_addr.s_addr = inet_addr(myIP.str());
    return(false); //:DEBUG:

    if (::connect(me, (SOCKADDR*)&sock, sizeof(SOCKADDR)) == SOCKET_ERROR) {
        lastErrCode = WSAGetLastError();
        closesocket(me);
        me = INVALID_SOCKET;
        return (false);
    }

    return (true);

}

1 个答案:

答案 0 :(得分:0)

感谢大家的回应。我已经解决了这个问题!我的主要代码没有愚蠢的Windows消息泵(我通常在Linux上运行这些类型的服务器)。我将其添加到主代码中,现在它可以正常工作。

#ifdef _WIN32
    MSG msg;
    while (!Stopped && GetMessage(&msg, (HWND)NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
#else
    while (!Stopped) {
        Sleep(1000);
    }
#endif

对不起,我没有足够的代码来实际运行示例,但是在调试和发行版本中,winsock代码都崩溃了100%。总是在RtlHeapxxx()或__acrt_lock()中崩溃。有了消息泵,我可以反复运行它。

对于gethostbyname问题,我正在调用内部的GetHostByName方法(区分大小写),并且它调用了较新的getaddrinfo()。

UINT32 Socket::getHostByName(const char * name, Data& ip) {
    UINT32 iadrs = getHostByName(name);
    ip.format("%d.%d.%d.%d", (iadrs >> 24) & 0xFF, (iadrs >> 16) & 0xFF, (iadrs >> 8) & 0xFF, iadrs & 0xFF);
    return (iadrs);
}

UINT32 Socket::getHostByName(const char * name) {

    if (lastAddress == name) {
        return(lastResolution);
    }

    struct addrinfo hints;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    struct addrinfo * result = nullptr;
    if (getaddrinfo(name, "80", &hints, &result) != 0) {
        if (result != nullptr) {
            freeaddrinfo(result);
        }
        return (0);
    }

    for (struct addrinfo * ptr = result; ptr != nullptr; ptr = ptr->ai_next) {
        if (ptr->ai_family == AF_INET) {
            struct sockaddr_in * ip = (struct sockaddr_in *) ptr->ai_addr;
            UINT32 iadrs = (ip->sin_addr.S_un.S_un_b.s_b1 << 24) | (ip->sin_addr.S_un.S_un_b.s_b2 << 16) | (ip->sin_addr.S_un.S_un_b.s_b3 << 8) | (ip->sin_addr.S_un.S_un_b.s_b4);
            freeaddrinfo(result);
            lastAddress = name;
            lastResolution = iadrs;
            return (iadrs);
        }
    }

    freeaddrinfo(result);
    return (0);

}