为了账号安全,请及时绑定邮箱和手机立即绑定

有谁碰到过类似问题么?或者是能指导一个努力的方向?

有谁碰到过类似问题么?或者是能指导一个努力的方向?

德玛西亚99 2023-03-19 21:17:32
linux服务器,在连接只有1000个时候,一切正常,到连接到2000以上的时候,就死循环在recv函数里面,cpu占用率很高,因为recv是系统函数,也不知道他在里面干什么。程序是epoll实现的。不是建立连接的时候死循环,而是跑了一段时间后,在调用recv函数的时候。我这里是服务器,接受连接, 是一个进程多个线程。每个线程管理多个连接。每个线程使用epoll方式响应网络事件,当网络可读的时候,就去调用recv函数读取数据。在进行测试的时候,发现1000个连接是好了,如果是3000个连接,跑一个晚上后,就有好几个线程死循环在系统的recv函数了。 
查看完整描述

2 回答

?
慕森卡

TA贡献1806条经验 获得超8个赞

给recv() 设个timeout, 过了这个时间就返回超时的错误,不要RECV一直阻塞在那里.

timeout 可以自己做一个。

下面是 google 弄得一段例子。
struct timeval tv; /* timeval and timeout stuff added by davekw7x */
int timeouts = 0;
tv.tv_sec = 3;
tv.tv_usec = 0;
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv))
{
perror("setsockopt");
return -1;
}

if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof their_addr) == -1) {
perror("connect");
exit(1);
}

while (((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) && (++timeouts < 1000)) { /* loop to retry in case it timed out; added by davekw7x */
perror("recv");
printf("After timeout #%d, trying again:\n", timeouts);
}
printf("numbytes = %d\n", numbytes);

buf[numbytes] = '\0';

printf("Received: %s",buf);

 


查看完整回答
反对 回复 2023-03-22
?
守着一只汪

TA贡献1872条经验 获得超4个赞

建议你用strace看那几个线程确切是卡在哪里

而且你描述的是,死循环。 recv函数怎么会死循环?

还有,当你的系统压力变大的时候, 会出现epoll提示某socket可用,但是等你去读的时候该socket已经被关闭的情况,你看看这种情况会不会对你的程序造成影响。 
----------------------------
man recv
RETURN VALUE
These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an
orderly shutdown.

你可以看到,当对端关闭socket的时候recv返回值是0。 那么作为你的程序,你又没有判断这种情况呢? 你默认的如果是使用EPOLLET模式, 你肯定不停的读socket直到EAGAIN出现,但是如果返回值0的话,并不会出现EAGAIN。

建议你还是多用strace来查询问题所在,有时候比gdb更能直接找出原因。

还有再纠正一点,recv是一个linux系统调用,要么是阻塞要么是返回,不存在死循环的问题的, 死循环肯定是出在你的程序代码中。 如果你觉得recv本身不退出又占用大量cpu,那就是linux库出bug或者是内核bug了。


查看完整回答
反对 回复 2023-03-22
  • 2 回答
  • 0 关注
  • 125 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号