使用select只在listen socket上?

时间:2015-05-13 08:59:26

标签: c++ sockets select

我目前正在为项目编写tcp服务器类和ClientHandle类。 是否有可能,服务器类只调用select上的fd_set只包含侦听器以检查新客户端是否连接?

Handle里面我想和套接字做类似的事情来检查我是否收到新请求,或者在向它发送数据之前它是否可写。

这样的东西?

int TCPServer::start()
{
    WSADATA wsaData;
    int iResult;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0)
    {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }

    struct addrinfo *result = nullptr, *ptr = nullptr, hints;

    ZeroMemory(&hints, sizeof (hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    // Resolve the local address and port to be used by the server
    iResult = getaddrinfo(nullptr, DEFAULT_PORT, &hints, &result);
    if (iResult != 0)
    {
        printf("getaddrinfo failed: %d\n", iResult);
        WSACleanup();
        return 1;
    }

    // Create a SOCKET for the server to listen for client connections
    //create socket to listen for clients
    m_listensocket = INVALID_SOCKET;
    m_listensocket = socket(result->ai_family, result->ai_socktype,
                            result->ai_protocol);
    if (m_listensocket == INVALID_SOCKET)
    {
        printf("Error at socket(): %ld\n", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }

    // Setup the TCP listening socket
    iResult = bind(m_listensocket, result->ai_addr, (int)result->ai_addrlen);
    if (iResult == SOCKET_ERROR)
    {
        printf("bind failed with error: %d\n", WSAGetLastError());
        freeaddrinfo(result);
        closesocket(m_listensocket);
        WSACleanup();
        return 1;
    }

    //free the result
    freeaddrinfo(result);

    //start listening
    if (listen(m_listensocket, SOMAXCONN) == SOCKET_ERROR)
    {
        printf("Listen failed with error: %ld\n", WSAGetLastError());
        closesocket(m_listensocket);
        WSACleanup();
        return 1;
    }
    //clear master set
    FD_ZERO(&m_set);
    //add the listen socket to the set
    FD_SET(m_listensocket, &m_set);
    return 0;
}
int TCPServer::acceptClient()
{
    auto temp_set = m_set;

    //setup the timeout to 100ms
    struct timeval tv;
    tv.tv_sec =  0;
    tv.tv_usec = 100;

    if (select(1, &temp_set, nullptr, nullptr, &tv) == -1)
    {
        //failed to select
        perror("fail in select method!");
        exit(4);
    }
    if (FD_ISSET(m_listensocket, &temp_set))
    {
        //we can accept a new
        SOCKET ClientSocket;
        ClientSocket = INVALID_SOCKET;
        // Accept a client socket
        struct sockaddr_storage their_addr; //stored address
        int sin_size = sizeof their_addr;
        ClientSocket = accept(m_listensocket,
                              reinterpret_cast<struct sockaddr *>(&their_addr),
                              &sin_size);
        if (ClientSocket == INVALID_SOCKET)
        {
            printf("accept failed: %d\n", WSAGetLastError());
            closesocket(m_listensocket);
            WSACleanup();
            return 1;
        }
        auto handle = new ClientHandle(ClientSocket);
        //now do whatever you want
    }
}

1 个答案:

答案 0 :(得分:1)

  

是否有可能,服务器类只调用仅包含侦听器的fd_set上的select来检查新客户端是否连接?

是的,这就是它的用途。

  

Handle里面我想和套接字做类似的事情来检查我是否收到新请求,或者在向它发送数据之前它是否可写。

是的,这就是它的用途。