我目前正在为项目编写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
}
}
答案 0 :(得分:1)
是否有可能,服务器类只调用仅包含侦听器的fd_set上的select来检查新客户端是否连接?
是的,这就是它的用途。
Handle里面我想和套接字做类似的事情来检查我是否收到新请求,或者在向它发送数据之前它是否可写。
是的,这就是它的用途。