c-发送大量内容后,我的send()调用使我的程序完全停止.这怎么可能?
作者:互联网
所以基本上我是用C制作一个在Linux上运行的MMO服务器.起初它可以正常工作,但在50个客户端的40秒后,它将完全暂停.当我调试它时,我发现基本上它停止响应之前打开的最后一帧是syscall(),此时它消失在内核中.一旦消失到内核中,它甚至不会返回任何值……这完全令人困惑.
50个客户端每250毫秒发送23个字节.然后,将这23个字节广播给所有其他49个客户端.此过程开始变慢,然后最终完全停止,在此内核永远不会从针对send()命令的系统调用返回.这里有什么可能的原因?这真让我发疯!
我发现的一个选择是强制延迟的Nagles算法.我尝试过切换,但是仍然会发生.
编辑:程序卡在这里.具体来说,在发送中,它依次调用syscall()
bool EpollManager::s_send(int curFD, unsigned char buf[], int bufLen, int flag)
// Meant to counteract partial sends
{
int sendRetVal = 0;
int bytesSent = 0;
while(bytesSent != bufLen)
{
print_buffer(buf, bufLen);
sendRetVal = send(curFD, buf + bytesSent, bufLen - bytesSent, flag);
cout << sendRetVal << " ";
if(sendRetVal == -1)
{
perror("Sending failed");
return false;
}
else
bytesSent += sendRetVal;
}
return true;
}
这也是调用s_send的方法.
void EpollManager::broadcast(unsigned char msg[], int bytesRead, int sender)
{
for(iMap = connections.begin(); iMap != connections.end(); iMap++)
{
if(sender != iMap->first)
{
if(s_send(iMap->first, msg, bytesRead, 0)) // MSG_NOSIGNAL
{
if(debug)
{
print_buffer(msg, bytesRead);
cout << "sent on file descriptor " << iMap->first << '\n';
}
}
}
}
if(connections.find(sender) != connections.end())
connections[sender]->reset_batch();
}
阐明连接是boost的unordered_map的一个实例.程序阻塞的数据也不是唯一的.它已经成功地广播到其他文件描述符,但是至少在一个看似随机的文件描述符上令人窒息.
解决方法:
内核为发送数据保留了一个有限的缓冲区.如果接收方没有接收到该缓冲区,则发送方将阻塞.这可能是问题吗?
标签:send,tcp,linux-kernel,linux,c-4 来源: https://codeday.me/bug/20191208/2094629.html