我正在尝试创建一个select-server以便从多个客户端接收连接(所有客户端都将连接到同一个端口)。
服务器接受前2个客户端,但除非其中一个客户端断开连接,否则它将不接受新客户端。
我开始像这样听服务器端口:
listen(m_socketId, SOMAXCONN);
并使用如下的select命令:
int selected = select(m_maxSocketId + 1, &m_socketReadSet, NULL, NULL, 0);
我添加了一些代码。
bool TcpServer::Start(char* ipAddress, int port)
{
m_active = true;
FD_ZERO(&m_socketMasterSet);
bool listening = m_socket->Listen(ipAddress, port);
// Start listening.
m_maxSocketId = m_socket->GetId();
FD_SET(m_maxSocketId, &m_socketMasterSet);
if (listening == true)
{
StartThread(&InvokeListening);
StartReceiving();
return true;
}
else
{
return false;
}
}
void TcpServer::Listen()
{
while (m_active == true)
{
m_socketReadSet = m_socketMasterSet;
int selected = select(m_maxSocketId + 1, &m_socketReadSet, NULL, NULL, 0);
if (selected <= 0)
continue;
bool accepted = Accept();
if (accepted == false)
{
ReceiveFromSockets();
}
}
}
bool TcpServer::Accept()
{
int listenerId = m_socket->GetId();
if (FD_ISSET(listenerId, &m_socketReadSet) == true)
{
struct sockaddr_in remoteAddr;
int addrSize = sizeof(remoteAddr);
unsigned int newSockId = accept(listenerId, (struct sockaddr *)&remoteAddr, &addrSize);
if (newSockId == -1) // Invalid socket...
{
return false;
}
if (newSockId > m_maxSocketId)
{
m_maxSocketId = newSockId;
}
m_clientUniqueId++;
// Remembering the new socket, so we'll be able to check its state
// the next time.
FD_SET(newSockId, &m_socketMasterSet);
CommEndPoint remote(remoteAddr);
CommEndPoint local = m_socket->GetLocalPoint();
ClientId* client = new ClientId(m_clientUniqueId, newSockId, local, remote);
m_clients.Add(client);
StoreNewlyAcceptedClient(client);
char acceptedMsg = CommInternalServerMsg::ConnectionAccepted;
Server::Send(CommMessageType::Internal, client, &acceptedMsg, sizeof(acceptedMsg));
return true;
}
return false;
}
我希望这够了:) 怎么了?
答案 0 :(得分:3)
到目前为止,select()
最常见的错误不是在每次迭代时重新初始化fd集。第二个,第三个和第四个参数由调用更新,因此您必须每次再次填充。
发布更多代码,以便人们可以真正帮助您。
fd_set
是一团糟:)
答案 1 :(得分:0)
不允许复制构造fd_set对象:
m_socketReadSet = m_socketMasterSet;
这与Nikolai的正确陈述相结合,即select
更改传入的集合可能会导致您的错误。
poll
(在Windows上,WSAPoll)是一个更友好的API。
Windows还提供WSAEventSelect
和(Msg)WaitForMultipleObjects(Ex)
,它在Unix上没有直接的等价物,但允许您等待套接字,文件,线程同步事件,定时器和UI消息。同一时间。