【问题标题】:Storing sockets in vectors to then close, same socket keeps getting added将套接字存储在向量中然后关闭,不断添加相同的套接字
【发布时间】:2017-01-06 22:32:00
【问题描述】:

我正在学习 C++ 和套接字,但遇到了一个问题,我创建了一个小示例应用程序来模拟它。我创建了一个监听套接字,然后连接到该套接字,并将客户端套接字存储在SOCKET * 类型的向量中。

在第三个客户端套接字连接之后,我遍历向量并关闭它。第一个 1 成功,但最后 2 个失败并出现 -1 错误,就好像套接字已经关闭一样。然而实际上只有 1 个套接字关闭。

下面是代码

WindowsSocket socketManager(&bitsLibrary);
    socketManager.createSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, 500, 1024, "127.0.0.1");

    socketManager.bindAndStartListening();
    vector<SOCKET *> clientSocketList;
    int i = 0;
    while (i < 3)
    {
        sockaddr_in client;
        SOCKET clientSock = socketManager.acceptClientAndReturnSocket(&client);

        cout << "Client Port: " << ntohs(client.sin_port) << endl;

        //Add the client socket to the vector
        clientSocketList.push_back(&clientSock);
        i++;

        string data = socketManager.receiveDataOnSocket(&clientSock);

        socketManager.sendToSocket(&clientSock, "Hello, here is a response");
    }

    int index = 1;
    for (std::vector<SOCKET *>::iterator it = clientSocketList.begin(); it != clientSocketList.end(); ++it)
    {
        cout << "Closing socket " << index << " of " << clientSocketList.size() << endl;
        try
        {
            SOCKET *socket = (SOCKET *)*it;
            socketManager.closeSocket(socket);
        }
        catch (SocketException ex)
        {
            cout << "Failed to close client socket. Error: " << ex.what() << endl;
        }
        index++;
    }

    //socketManager.closeSocket(socketManager.returnSocket());
    //socketManager.closeSocket(&clientSock);

    return EXIT_SUCCESS;

创建socket函数如下:

bool WindowsSocket::createSocket(int family, int socketType, int protocol, int port, int bufferLength, string ipAddress)
{
    stringstream logstream;
    //Call the base method to do the prep work e.g. create the buffer
    BaseSocket::createsocket(port, bufferLength);

    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0)
    {
        logstream << "WSAStartup failed with error: " << iResult;
        this->bitsLibrary->writeToLog(logstream.str(), "WindowsSocket", "createSocket");
        logstream.clear();
        logstream.str(string());
        return false;
    }
    this->serverSocket = socket(family, socketType, protocol);
    this->serv_addr.sin_family = family;
    if (ipAddress.empty())
    {
        this->serv_addr.sin_addr.s_addr = INADDR_ANY;
    }
    else
    {
        this->serv_addr.sin_addr.s_addr = inet_addr(ipAddress.c_str());
    }
    this->serv_addr.sin_port = htons(port);

    return true;
}

bindAndStartListening函数如下:

bool WindowsSocket::bindAndStartListening(int backlog)
{
    stringstream logstream;

    //iResult = ::bind(this->serverSocket, result->ai_addr, (int)result->ai_addrlen);
    iResult = ::bind(this->serverSocket, (SOCKADDR *)&this->serv_addr, sizeof(this->serv_addr));
    if (iResult != 0)
    {
        logstream << "Socket binding failed with error: " << iResult;
        this->bitsLibrary->writeToLog(logstream.str(), "WindowsSocket", "bindAndStartListening");
        logstream.clear();
        logstream.str(string());
        FreeAddrInfo(result);
        closesocket(this->serverSocket);
        WSACleanup();
        return false;
    }

    freeaddrinfo(result);
    iResult = listen(this->serverSocket, backlog);
    if (iResult == SOCKET_ERROR)
    {
        throw SocketException(this->getErrorStringFromErrorCode(WSAGetLastError()).c_str());
        return false;
    }
    logstream << "Socket has binded and is now listening";
    this->bitsLibrary->writeToLog(logstream.str(), "WindowsSocket", "bindAndStartListening");
    return true;
}

acceptClientAndReturnSocket函数如下:

SOCKET WindowsSocket::acceptClientAndReturnSocket(sockaddr_in *clientAddr)
{
    SOCKET clientSocket = INVALID_SOCKET;
    //sockaddr_in clientAddr;
    socklen_t sin_size = sizeof(struct sockaddr_in);
    clientSocket = accept(this->serverSocket, (struct sockaddr*)clientAddr, &sin_size);
    return clientSocket;
}

当我调试 ``clientSocketList` 包含的内容时,每个项目似乎包含相同的值,如下面的屏幕截图所示:

我不明白为什么将同一个客户端套接字添加到向量中。

【问题讨论】:

    标签: c++ sockets vector


    【解决方案1】:

    while(i &lt; 3) 循环的每次迭代都会创建一个新的SOCKET。您保存它的地址,但它在迭代结束时被销毁。您保存的是堆栈上对象的地址,并且每次迭代最新的clientSock 都在同一个地址。

    clientSocketListstd::vector&lt;SOCKET*&gt;,而您可能想使用 std::vector&lt;SOCKET&gt;

    【讨论】:

    • 啊,当然,每次我认为我完全理解了指针时,都会发生一些事情,然后我再次改变主意
    • 您在这段代码中几乎所有的指针使用似乎都没有必要。例如,当acceptClientAndReturnSocket 可以接受引用或返回std::pair 时,为什么还要接受指针?
    • 嗯,好点,我使用了一个指针,所以当它通过套接字时它不会创建副本,我不知道引用 - 仍然不完全 - 当我编写方法时最初,但是是的,可能会回去看看我能改变什么。尽管我认为我找到了指针而不是引用的一个原因是,如果它作为 ref 传递,则传递值不明显可以更改,如果它是指针,则可以修改它,尽管它可能应该是 const指针
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-19
    • 2016-10-05
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    相关资源
    最近更新 更多