免费注册 查看新帖 |

Chinaunix

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

[C++] recv函数出现死循环 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-09-08 14:13 |只看该作者 |倒序浏览
int CSESocket::RecvData(char *p_fName, int p_iRecvLen, int p_iTimeout)
{
    int iRet;
    char strlog[200+1];
    char strRev[CONTENT_LEN+1];
    struct timeval timeout;
    timeout.tv_sec = 30;
    fd_set fdReads;
    while(1)
    {
        FD_ZERO(&fdReads);
        FD_SET(m_iSock,&fdReads);

        iRet = select(m_iSock+1,&fdReads,NULL,NULL,&timeout);
        if(iRet==-1)
        {
            return -1;
        }
        if(FD_ISSET(m_iSock,&fdReads))
        {
            //iRet = recv(m_iSock,p_strRecv,sizeof(strRev),0);

            FILE *fpWeb;
            fpWeb = fopen(p_fName,"w");
            while (1)   
            {
                memset(strRev, 0, sizeof(strRev));
                iRet = recv(m_iSock,strRev,sizeof(strRev),0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (iRet == WSAECONNRESET || iRet == SOCKET_ERROR || iRet <= 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(fpWeb,"%s",strRev);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fflush(fpWeb);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fclose(fpWeb);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fpWeb = NULL;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;return iRet;
}


我用socket来获取一个网页内容,网页比较大大概347k.我用循环使用recv的办法来把网页保存到文件中,但是在最后一次recv时,recv函数却出现了死循环,这是为什么呢

论坛徽章:
4
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11IT运维版块每日发帖之星
日期:2016-08-11 06:20:00IT运维版块每日发帖之星
日期:2016-08-15 06:20:00
2 [报告]
发表于 2008-09-08 14:47 |只看该作者

回复 #1 jiangf 的帖子

socket是堵塞方式的吧?
此时recv是堵塞方式的,会一直等到有数据返回,或者网络连接断开。
正确的做法是把select和recv放在同一个循环中,通过select实现超时。

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
3 [报告]
发表于 2008-09-08 16:01 |只看该作者
或者用异步

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
4 [报告]
发表于 2008-09-08 16:23 |只看该作者
估计你的socket是阻塞式接收,如果你发的是HTTP/1.1的请求,Web服务器默认是长连接,传完数据后recv自然就block了。
两种方法可以避免这种情况:
1 Get请求中加上Connection: Close,服务器就会断开连接,recv就返回0
2 更灵活的方法是设置socket为非阻塞

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
5 [报告]
发表于 2008-09-08 18:10 |只看该作者
1. 又是select的问题..超时值每次都要设的..
2. recv 只能返回-1(出错时).判断错误码应该用errno

论坛徽章:
0
6 [报告]
发表于 2008-09-08 21:43 |只看该作者
感觉就像iRet返回0了,造成select总是处于可读状态。
于是select不起作用,一遍一遍的读取返回0字节

修改一下就可以了,如果返回0,表示socket对方已经关闭,这边也关闭,没有必要继续读。就可以了吧

论坛徽章:
0
7 [报告]
发表于 2008-09-15 11:29 |只看该作者
原帖由 timespace 于 2008-9-8 16:23 发表
估计你的socket是阻塞式接收,如果你发的是HTTP/1.1的请求,Web服务器默认是长连接,传完数据后recv自然就block了。
两种方法可以避免这种情况:
1 Get请求中加上Connection: Close,服务器就会断开连接,rec ...

我把Connect参数改成Close后抓取静态的网页已经可以了,但是在抓取动态网页时,抓取下来的内容怎么都少了body内的正文
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP