2015-05-13 6 views
0

В настоящее время я пишу класс сервера tcp и класс ClientHandle для проекта. Возможно ли, что класс сервера просто вызовет select на fd_set, содержащий только listensocket, чтобы проверить, подключен ли новый клиент?использовать только для прослушивания гнезда?

Внутри ручки я хотел бы сделать подобное с сокетом, чтобы проверить, получил ли я новый запрос или если он можно записать перед отправкой данных на него.

Что-то вроде этого?

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

Можно ли, что класс сервер просто назвать выбор на fd_set только содержащей listensocket, чтобы проверить, если новый клиент подключается?

Да, это для чего.

Внутри ручки я хотел бы сделать аналогичный с сокетом, чтобы проверить, получил ли я новый запрос или его можно записать перед отправкой данных на него.

Да, это для чего.

+0

Спасибо за короткий и ясный ответ на этот, возможно, бесполезный вопрос. Был смущен, потому что мне нужно положить его в сет. Но да, конечно, полезно, если несколько соединений должны быть проверены вместе. – BennX

Смежные вопросы