recv函数linux,linux 下调用recv函数,死循环在recv函数里面,什么原因?

在Linux服务器上,程序使用epoll实现并发处理连接。当连接数超过一定数量(如2000)时,部分线程在recv函数中出现死循环,CPU占用率升高。问题可能出现在当socket被关闭时,recv没有正确处理返回值0的情况。建议使用strace分析线程卡住的具体位置,并检查是否处理了对端关闭连接时recv返回0的情况。另外,设置recv超时也是一个解决思路。
摘要由CSDN通过智能技术生成

linux 下调用recv函数,死循环在recv函数里面,什么原因?

linux服务器,在连接只有1000个时候,一切正常,到连接到2000以上的时候,就死循环在recv函数里面,cpu占用率很高,因为recv是系统函数,也不知道他在里面干什么。程序是epoll实现的。 有谁碰到过类似问题么?或者是能指导一个努力的方向? 回1楼:不是建立连接的时候死循环,而是跑了一段时间后,在调用recv函数的时候。 我这里是服务器,接受连接, 是一个进程多个线程。每个线程管理多个连接。每个线程使用epoll方式响应网络事件,当网络可读的时候,就去调用recv函数读取数据。 在进行测试的时候,发现1000个连接是好了,如果是3000个连接,跑一个晚上后,就有好几个线程死循环在系统的recv函数了。 回2楼:调试出问题的程序后,发现几个线程都停留在recv函数里面,n单步执行后,直接跳出这个线程。 之所以说是死循环,因为在这种情况下这几个相关线程的cpu占用都很高。 如果是因为socket已经非法,那么我该怎么提前规避处理? 回3楼:socket都是非阻塞的。

更新时间:2019-05-19 19:50

最满意答案

建议你用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了。

2009-12-30 回答

其他回答

send后,操作系统会决定是不是马山发包还是继续等待看看还有别的send,然后把他们一起打成一个包来发送。所以你recv是不知道要接收几个包的。

2009-12-31 回答

给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);

2009-12-31 回答

相关问答

建议你用strace看那几个线程确切是卡在哪里 而且你描述的是,死循环。 recv函数怎么会死循环? 还有,当你的系统压力变大的时候, 会出现epoll提示某socket可用,但是等你去读的时候该socket已经被关闭的情况,你看看这种情况会不会对你的程序造成影响。 ---------------------------- man recv RETURN VALUE These calls return the number of bytes received, or -1 if an error

...

recv是socket编程中最常用的函数之一,在阻塞状态的recv有时候会返回不同的值,而对于错误值也有相应的错误码,分别对应不同的状态,下面是我针对常见的几种网络状态的简单总结。 首先阻塞接收的recv有时候会返回0,这仅在对端已经关闭TCP连接时才会发生。 而当拔掉设备网线的时候,recv并不会发生变化,仍然阻塞,如果在这个拔网线阶段,socket被关掉了,后果可能就是recv永久的阻塞了。 所以一般对于阻塞的socket都会用setsockopt来设置recv超时。 当超时时间到达后,rec

...

建议你用strace看那几个线程确切是卡在哪里 而且你描述的是,死循环。 recv函数怎么会死循环? 还有,当你的系统压力变大的时候, 会出现epoll提示某socket可用,但是等你去读的时候该socket已经被关闭的情况,你看看这种情况会不会对你的程序造成影响。 ---------------------------- man recv RETURN VALUE These calls return the number of bytes received, or -1 if an error

...

您可以使用setsockopt函数在接收操作上设置超时: SO_RCVTIMEO 设置超时值,指定输入函数等待直到完成的最大时间量。 它接受时间结构,秒数和微秒数指定等待输入操作完成的时间限制。 如果接收操作在没有接收到附加数据的情况下阻塞了这么多时间,则如果没有接收到数据,则它将返回部分计数或errno设置为[EAGAIN]或[EWOULDBLOCK]。 该选项的默认值为零,表示接收操作不会超时。 此选项需要一个时间结构。 请注意,并非所有实现都允许设置此选项。 // LINUX

struct

...

recv()在流的末尾返回零,这在对等体关闭连接时发生。 关于它没有任何“随机”。 recv() returns zero at end of stream, which in turn occurs when the peer closes the connection. There is nothing 'random' about it.

你有多确定segfault是在recv() ? 您对recv()调用看起来很好,但是,之前的一行是写入未分配的内存,这将导致段错误: std::cin >> tempString;

尝试像这样声明tempString : #define INPUT_BUF_SIZE 100

char tempString[INPUT_BUF_SIZE + 1];

此外,这段代码似乎不寻常: echoStringLen = strlen(echoString); /* Determine in

...

忘了将此标记为已解决。 所有套接字实例都从套接字基类继承其文件描述符变量。 TCPSocket类有一个重载的fd var,它被设置而不是基本的fd。 Forgot to mark this as solved. All socket instances inherit their file descriptor vars from a socket base class. The TCPSocket class had an overloaded fd var that was getting s

...

您希望shutdown(fd, SHUT_WR)仅关闭写入但仍能够读取。 close(fd)将使文件描述符无效,就像关闭了本地文件的开放路径一样。 http://man7.org/linux/man-pages/man2/shutdown.2.html You want shutdown(fd, SHUT_WR) to close only for writes but still be able to read. close(fd) will invalidate the file descri

...

C ++代码中的许多错误 - 比如if (bytesSent = 0) ,这是一个结果转换为boolean的赋值,所以总是返回false 。 您不注意从TCP套接字读取的字节数,假设您在发送时收到一条完整的消息 - 这是错误的,因为您可能正在阅读部分消息,多于一条消息或介于两者之间的任何内容 - 它是一个原始字节流 。 检查-1显式返回系统调用,然后检查errno(3)的值,比如说strerror(3)函数来找出出错的地方。 编辑0: 您正在尝试使用侦听套接字sSock进行数据传输 - 错误 -

...

如果通信中发生错误,则会在套接字上设置错误,并与下一个与套接字相关的系统调用一起传递。 EHOSTUNREACH错误可以(通过其他方式)通过向目标发送UDP数据包并使ICMP无法访问来触发。 由于此ICMP消息仅在send调用完成后才返回,因此它不会返回send而只返回到套接字上的下一个系统调用,也可能是一个recv 。 因此我建议在Linux中也可以返回此错误,但我可能错了。 通常Linux不是UNIX,系统发展和文档通常是有缺陷的。 如果你在各种平台上查看recv的文档,你会发现OpenBSD

...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值