Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1151089
  • 博文数量: 241
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 2279
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-27 19:53
个人简介

JustForFun

文章分类

全部博文(241)

文章存档

2023年(8)

2022年(2)

2021年(3)

2020年(30)

2019年(11)

2018年(27)

2017年(54)

2016年(83)

2015年(23)

我的朋友

分类: LINUX

2016-09-18 10:49:59

原文

http://www.blogbus.com/gcoder-logs/220779725.html

考虑下面的场景,server向client发送数据"_META_DATA_\r\n_USER_DATA_",要求"\r\n"之前的数据 _META_DATA_在第一次recv中接收,剩下的recv调用读取_USER_DATA_部分的数据。因为tcp是stream协议,并且 _META_DATA_数据不是定长的,所以没有办法保证一次recv调用不读到_USER_DATA_部分的数据,除非一次读取一个字符。这种场景 下,recv的MSG_PEEK参数就发挥作用。

recv的原型是ssize_t recv(int s, void *buf, size_t len, int flags); 通常flags都设置为0,此时recv函数读取tcp buffer中的数据到buf中,并从tcp buffer中移除已读取的数据。把flags设置为MSG_PEEK,仅把tcp buffer中的数据读取到buf中,并不把已读取的数据从tcp buffer中移除,再次调用recv仍然可以读到刚才读到的数据。

 

针对上面的场景,recv(fd, buf, nbuf, MSG_PEEK) 查看数据,查看"\r\n"的位置pos,再recv(fd, buf, pos+2, 0) 读取(并移除)数据。

 

上述场景描述的比较极端,毕竟很多时候,就算在一次recv中读到了_USER_DATA_部分的数据,仍可以先把这部分数据保存起来,添加到后续 的recv数据之前,但是如果不同的recv跨越很多函数,保存数据带来了额外的复杂度。还可以考虑另外的场景,同一个端口支持文本协议和二进制协议,利 用MSG_PEEK看一下头几个字符,先判断是文本协议还是二进制协议,再做请求分发,也是不错的选择。当然,真正的recv之前调用使用 MSG_PEEK导致额外的一次函数调用。



////////////////////////
http://blog.csdn.net/pi9nc/article/details/17165171

  • TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠**。收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端 为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封 包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。 即面向流的通信是无消息保护边界的。
  • UDP(user datagram protocol,用户数据报协议)是无连接的,面向消息的,提供高效率服务。不会使用块的合并优化算法,, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头 (消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。

阅读(3364) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~