2015-05-13 13 views
0

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

内部的句柄我想做类似的套接字来检查是否有新的请求,或者如果它是可写之前发送数据。

这样的事情?

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

是否有可能,服务器类调用Select只包含listensocket以检查是否有新的客户端连接一个FD_SET?

是的,就是这样。

在句柄的内部我想做类似的套接字来检查是否有新的请求,或者如果它是可写的之前发送数据。

是的,就是这样。

+0

非常感谢您对这个可能无用的问题的简短而明确的答案。感到困惑,因为我需要把它放到集合中。但是,如果应该一起检查多个连接,那么肯定有用。 – BennX