C++ Winsock 10093错误

5

我正在尝试用C++构建一个可以接受多个客户端的服务器。为此,我构建了一个winsock包装器,并使用boost线程进行每个客户端的通信。
当我尝试接受客户端时,我遇到了一个奇怪的问题。我的循环看起来像这样:

int clientID = 0;
listenSocket = new Socket(SocketType::TCP);
listenSocket->Bind(port);
listenSocket->Listen();

while(running)
{
    Socket *socket = &listenSocket->Accept();
    mutex.lock();
    clients.push_back(new Client(socket,  clientID));
    mutex.unlock();

    std::cout << "Client with id " << clientID << " connected!" << std::endl;

    std::cout << WSAGetLastError() << std::endl;

    clientID++;
}

现在,第一个客户端已经接受了并且WSAGetLastError()返回0,但是在第一个连接后,即使我不尝试连接另一个客户端,它仍然在控制台中不断写入10093,这意味着循环中的Accept()停止阻塞,并且由于某种原因无法正确接受。我在网上读到,这个错误是由于没有调用WSAStartup()引起的,但是我在套接字的构造函数中调用了它,并且它在第一次接受时确实接受了。


你可能在某个析构函数中调用了WSACleanup吗? - Retired Ninja
2个回答

18

10093代表WSANOTINITIALISED,其含义包括:

  • 在调用 WSAStartup() 之前就进行了套接字调用。

  • 在调用与 WSAStartup() 相同次数的 WSACleanup() 后进行了套接字调用。

根据您提供的代码,似乎 Socket::Accept() 返回了一个值为 Socket 对象而不是指向 Socket* 的指针。如果是这样,那么 Accept() 将创建一个临时的 Socket,并在分配给 Socket *socket 后立即超出作用域。很可能 Socket 析构函数调用了 WSACleanup(),而此时却不应该这样做。对 WSAStartup()WSACleanup() 的调用必须始终保持平衡。

最佳时间来调用 WSAStartup() 是在程序启动时,而不是在对象的构造函数内部。同样地,最佳时间来调用 WSACleanup() 是在程序清理退出之前,而不是在对象的析构函数内部。


在我的情况下,我在closesocket()之前调用了WSACleanup()函数。所以它给了我一个WSANOTINITIALISED错误,如此处所述:) - Zrn-dev
在我的情况下,我在调用closesocket()函数之前调用了WSACleanup()函数。因此,它给了我一个WSANOTINITIALISED错误,就像这里提到的一样:) - Zrn-dev

13

我在编写一个跨平台的套接字应用程序时遇到了完全相同的问题。它在Linux和OS X上运行良好,但是在Windows上出现了10093错误。要解决此问题,请在调用任何winsock函数之前添加以下代码:

    #ifdef WIN32
        // Initialize Winsock
        int iResult;
        WSADATA wsaData;
        iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
        if (iResult != 0) {
            std::cout << "WSAStartup failed: " << iResult << std::endl;
            return;
        }
    #endif

3
谢谢 - 这正是我的问题所在 - 我没有在if/else的所有分支中执行WSAStartup()。 - WonderfulDay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接