免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 17657 | 回复: 8
打印 上一主题 下一主题

设置socket为非阻塞时, recv一直返回EINTR? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-01-14 22:45 |只看该作者 |倒序浏览
这几天写的一个telnet客户端类, 这个类被别的程序调用, 跟server发命令并取结果.所有的操作都不能无限时等待. 所以必须加时间控制, 可是出现了一些怪问题

程序没有设置阻塞时, 一切正常, 只是有些地方会一直等下去, 无法响应用户操作.但
1. 用setsockopt将recv的timeout设为一秒(就是SO_RCVTIMEO选项), 可以在windows下正常工作, 不过在unix下, 这句一直返回-1, error为EINTR. 我用while来一直setsockopt, 每次返回值都是这样, 而且没一次设置成功
  struct timeval tv_out struct timeval tv_out;
        tv_out.tv_sec = 1;
        tv_out.tv_usec = 0;
        setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv_out, sizeof(tv_out));
因为这个类是一个很大的程序里一个小小的功能, 我也搞不清其它地方对信号是怎么处理的, 所以猜测程序其它地方有用信号, 但如果不设置阻塞, recv并不返回EINTR, 证明程序里并没有产生信号
我试着getsockopt,同样的选项, 返回值里那个长度总是0, 也就是根本没返回任何东西.

2.  如果用fcntl或ioctl将m_socket设置为非阻塞, 这个操作可以成功, 但后面所有的recv全部直接返回,errno为EINTR


3. 最后还是用select实现了, 不将socket 设为阻塞, 只是读数据之前都先select一下, 一切正常了,  select也没收到EINTR.

所以请教一下,
1.用setsockopt的时候出错, 可能原因是什么?
2.将描述字设为阻塞后, 无数据可读时errno应该是EAGAIN, 一直是EINTR, 可能的原因是什么呢

论坛徽章:
0
2 [报告]
发表于 2006-01-14 23:04 |只看该作者
忘了说开发环境,
WINDOWS下是VC6+WIN2000
UNIX是SUN OS 5.8+gcc

论坛徽章:
0
3 [报告]
发表于 2006-01-14 23:57 |只看该作者
EINTR很正常啊
当返回EINTR时要重新select

论坛徽章:
0
4 [报告]
发表于 2006-01-15 02:07 |只看该作者
原帖由 FH 于 2006-1-14 23:57 发表
EINTR很正常啊
当返回EINTR时要重新select

我不是说用select时, 用select是正常的
我是说用ioctl或fcntl设置描述字为非阻塞后, 后面recv操作一次都成功不了了, 没一次不EINTR.
而实际上根本没信号发生, 我不没为非阻塞, 执行recv的时候有的成功, 有的阻塞, 根本没哪个调用收到信号.
而且为什么说EINTR正常呢?非阻塞时,应该EAGAIN才正常啊

至于那个用setsockopt, 后来才看到有说法,SUN OS不支持SO_RCVTIMEO选项, 不知道为什么要把errno设为EINTR

论坛徽章:
0
5 [报告]
发表于 2006-01-15 11:47 |只看该作者
没玩过SUN,不知道

论坛徽章:
0
6 [报告]
发表于 2006-01-15 11:52 |只看该作者
屏蔽掉EINTR,也收不到东西吗?

if (errno == EINTR ) continue;

论坛徽章:
0
7 [报告]
发表于 2006-01-15 16:25 |只看该作者
我也遇到过此种情况,也没太明白什么意思,不过程序调试通过后也一直没时间管这些了,希望有明白这块的可以说说这块的机制是怎么实现的!谢谢!

论坛徽章:
0
8 [报告]
发表于 2006-01-15 22:38 |只看该作者
原帖由 zhhui2000 于 2006-1-15 11:52 发表
屏蔽掉EINTR,也收不到东西吗?

if (errno == EINTR ) continue;

我就是这样做的,结果限入死循环

论坛徽章:
0
9 [报告]
发表于 2011-06-27 21:49 |只看该作者
if(errno == EINTR
                                || errno == EAGAIN
                                || errno == EWOULDBLOCK)
                        {
                                printf("[ERROR] %s\n", strerror(errno));
                                continue;
                        }

----------------------
超时肯定是会发生的,只是超时的时候怎么去判断?

就是一超时立即触发别的操作~~ 我要知道超时这个"事件"
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP