免费注册 查看新帖 |

Chinaunix

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

[Linux] socket的两个问题 大牛指点 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-11-29 16:20 |只看该作者 |倒序浏览

1
创建socket的时候 我们可以设置它为阻塞或者非阻塞,那么在recv/send时,flag参数指定的阻塞和非阻塞和socket本身有没有关系没有、

从驱动层面分析,如果socket阻塞的时候,从socket读数据都为阻塞的。如果是这样那么recv时指定的flag参数如何解释 ,是忽略它呢 还是重新将socket指定为
flag指定的方式(阻塞或非阻塞)进行读写数据,求大牛指点

2
recv数据的时候,我们recv一次有可能数据接收不完,但是到底要recv多少次才算完呢?

int buf[512];

i = 0;
alllen = 0;
while(1)
{
        len = recv(socket,buf, 512, 0);
        if (len > 0)
        {       
                alllen += len;
                /* framedata为真正完整想要数据的缓冲,可以认为很大 */
                putbuf(framedata + i * 512 , buf, len);
                if (len <512 )
                        break;
                i++;
        }

}
deal(framedata, alllen);

像上面的代码 猛看起来没问题,但是仔细分析还是存在问题的,如果想要的数据 2050字节,那么我recv 5次即可以收完,
但是如果想要的数据是2048字节 就存在问题,recv完成4次后,还会一直在接收数据,何时是个头呀 ?
请教大牛这时 如何判断数据接收完成。
请注意前提是你不知道对方发的一包长度是多少,可能是2050也可能是2048? 这时 如何准确判断收完完整的一包数据?



论坛徽章:
0
2 [报告]
发表于 2013-11-29 17:11 |只看该作者
本帖最后由 pirloofmilan 于 2013-11-29 17:16 编辑

创建socket的时候 我们可以设置它为阻塞或者非阻塞,那么在recv/send时,flag参数指定的阻塞和非阻塞和socket本身有没有关系没有
int socket(int domain, int type, int protocol);
创建socket的时候是没有办法指定其是否阻塞的
可以通过setsockopt或者fcntl设置socket为阻塞或者非阻塞的
有4种组合
1. socket阻塞,recv/send默认:阻塞处理
2. socket阻塞,recv/send指定非阻塞:非阻塞处理
3. socket非阻塞,recv/send默认:非阻塞处理
4. socket非阻塞,recv/send指定非阻塞:非阻塞处理

从驱动层面分析,如果socket阻塞的时候,从socket读数据都为阻塞的。如果是这样那么recv时指定的flag参数如何解释 ,是忽略它呢 还是重新将socket指定为
flag指定的方式(阻塞或非阻塞)进行读写数据

就是上面的情况1和2

recv数据的时候,我们recv一次有可能数据接收不完,但是到底要recv多少次才算完呢?

recv默认阻塞,如果socket上面没有数据可读,那么recv就会一直阻塞在那里,直到有数据进入socket,像你说的这种情况,我们就必须预知数据的长度,比如HTTP协议就会在其头部有一个content length字段,告诉客户端我有多少数据要发过来。
也就是说客户端和服务器端必须按照一定的规则进行通信,这就是RFC定义的那些协议(比如HTTP DNS等等)存在的必要性了
当然,为了程序的健壮性,我们必须考虑特殊情况,比如客户端去读socket,但是此时服务器端却关掉了,那么此时recv是不是就永远阻塞了?但是我们可以设置一个timeout时间,比如超过30s读不到,那就失败返回,或者retry,等到服务器恢复正常,我们就可以再次读到数据了

总之,socket编程的真正难度是怎么处理各种异常情况

论坛徽章:
0
3 [报告]
发表于 2013-11-29 19:37 |只看该作者
首先谢谢大牛
第1个问题你是验证过的吗 还是说在哪里看的?
明白了 我原来说的创建SOCKET时设置阻塞和非阻塞意思 是指用setsockopt或fcntl,是我没表述清楚  谢谢纠正
recv的时候 ,利用超时是不错的方案(如果到来数据长度不定的话)

论坛徽章:
1
2015亚冠之迪拜阿赫利
日期:2015-07-01 18:38:38
4 [报告]
发表于 2013-11-29 21:12 |只看该作者
用select或者epoll模型时,当有数据时,通知程序,然后再调用recv(就是确定有数据再调用)
如果不用的话在长度不定的时候应该只能阻塞等待或者非阻塞循环

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
5 [报告]
发表于 2013-12-01 11:10 |只看该作者
建议多读书,闭门造车进步太慢。

论坛徽章:
1
技术图书徽章
日期:2014-01-07 00:12:45
6 [报告]
发表于 2013-12-31 01:03 |只看该作者
问题很好,回答很好,学习了!

论坛徽章:
0
7 [报告]
发表于 2014-02-11 10:27 |只看该作者
赞,学习了。

论坛徽章:
0
8 [报告]
发表于 2014-02-12 10:46 |只看该作者
最理想的情况,接收的数据有结束标示,每次接收,判断数据是否接收完。比如用pop3接收邮件的时候,由于邮件格式是标准的(rfc文档规定),邮件是以“.\r\n”结束的,这样就可以判断邮件是否完整
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP