【发布时间】:2013-10-06 17:48:01
【问题描述】:
我有 2 个线程:
线程 A: 这是 select() 循环。为读取操作执行套接字处理,例如接受新连接、接收数据。
while (1) {
FD_ZERO(&fdReadSet);
numActiveSockets = 0;
for (std::unordered_map<SOCKET, TcpSocket*>::iterator it = m_sock_table.begin(); it != m_sock_table.end(); it++)
{
numActiveSockets++;
FD_SET(it->first, &fdReadSet);
}
int ret;
bool hasListen = false;
if (( ret = select(numActiveSockets, &fdReadSet, NULL, NULL, NULL)) == SOCKET_ERROR) {
printf("Select Failed, Error code = %d\n", WSAGetLastError());
return -1;
}
for (std::unordered_map<SOCKET, TcpSocket*>::iterator it = m_sock_table.begin(); it != m_sock_table.end(); it++)
{
if (FD_ISSET(it->first, &fdReadSet))
{
if (it->first == TcpSocket::m_listen_sock)
{
if (!hasListen)
{
sockaddr_in sock_addr;
int sockLength = sizeof(sock_addr);
SOCKET sock = accept(it->first, (sockaddr *) &sock_addr, &sockLength);
TcpSocket * socket = new TcpSocket();
socket->m_sock = sock;
m_sock_table[sock] = socket;
it = m_sock_table.begin();
hasListen = true;
}
}
else
{
char * buffer = it->second->GetWriteBuffer();
int numRead = recv(it->first, buffer, SOCKET_BUFFER_SIZE, 0);
if (numRead == SOCKET_ERROR)
{
int err = WSAGetLastError();
if (err == WSAECONNRESET)
{
printf("Connection [%i]: RESET Received. Closing Socket\n", it->first);
closesocket(it->first);
it = socketVector.erase(it->first); // iterator invalidated after erase
}
else
{
printf("Recv Failed. Error code = %d\n", err);
return -1;
}
}
else if (numRead == 0)//connection close
{
printf("Connection [%i]: Graceful exit. Closing Socket\n", it->first);
closesocket(it->first);
it = socketVector.erase(it->first); // iterator invalidated after erase
}
else {
/* Process received data */
}
}
}
}
}
线程 B: 允许应用程序执行 connect() 以建立新连接。如果 connect() 成功,它会将返回的套接字添加到 m_sock_table。
我有一个名为 m_sock_table 的套接字表,其中包含所有套接字。我使用这个 m_sock_table 来初始化要在 select() 中使用的 fdReadSet。
------------问题-----
如果线程 A 被 select() 阻塞,同时线程 B 通过 connect() 建立新连接,应用程序将无法从新连接接收数据,因为 fdReadset 尚未使用新连接的套接字进行更新。
什么是解决这个问题的好方法?还是设计一开始就错了?
【问题讨论】:
-
什么事件导致添加新连接?如果您 select() 超时,则可以将新连接添加到表中。然后,您可以将超时设置为创建连接和提供连接之间可接受的延迟。
-
谢谢。我最终使用了你的方法。如果您愿意发布答案,我很乐意将其标记为已接受。
标签: multithreading sockets select networking tcp