【问题标题】:C++ Winsock 10093 errorC++ Winsock 10093 错误
【发布时间】:2023-10-28 16:21:02
【问题描述】:

我正在尝试用 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,比如在析构函数中?

标签: c++ winsock


【解决方案1】:

10093 是WSANOTINITIALISED,这意味着要么根本没有调用WSAStartup(),要么调用WSACleanup() 的次数多于调用了WSAStartup() 的次数。

根据您提供的代码,Socket::Accept() 似乎返回 Socket 而不是 Socket*。如果是这样,那么Accept() 正在创建一个临时的Socket,它在分配Socket *socket 后立即超出范围。 Socket 析构函数很可能在不应该调用WSACleanup() 时调用。对WSAStartup()WSACleanup() 的调用必须始终保持平衡。

【讨论】:

    【解决方案2】:

    我在编写跨平台套接字应用程序时遇到了完全相同的问题。它在 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
    

    【讨论】:

    • 谢谢 - 这是我遇到的问题 - 我没有在 if/else 的所有分支中执行 WSAStartup()