考虑下面的场景,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导致额外的一次函数调用。

recv函数的MSG_PEEK标志介绍的更多相关文章

  1. UNIX网络编程——send与recv函数详解

    #include <sys/socket.h> ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags); ssize_ ...

  2. socket函数send和recv函数

    转自:http://www.cppblog.com/aaxron/archive/2012/04/27/172891.html 在发送端,一次发送4092个字节,在接收端,一次接收4092个字节,但是 ...

  3. Linux下tcp协议socket的recv函数返回时机分析(粘包)

    http://www.vckbase.com/index.php/wv/10http://blog.csdn.net/zlzlei/article/details/7689409 文章一: 当前在网络 ...

  4. socket使用TCP协议时,send、recv函数解析以及TCP连接关闭的问题

    Tcp协议本身是可靠的,并不等于应用程序用tcp发送数据就一定是可靠的.不管是否阻塞,send发送的大小,并不代表对端recv到多少的数据. 在阻塞模式下, send函数的过程是将应用程序请求发送的数 ...

  5. send()和recv()函数详解

    send()函数 int send( SOCKET s, const char FAR *buf, int len, int flags ); 不论是客户还是服务器应用程序都用send函数来向TCP连 ...

  6. linux内核中send与recv函数详解

    Linux send与recv函数详解 1.简介 #include <sys/socket.h> ssize_t recv(int sockfd, void *buff, size_t n ...

  7. linux Socket send与recv函数详解

    转自:http://www.cnblogs.com/blankqdb/archive/2012/08/30/2663859.html linux send与recv函数详解   1 #include ...

  8. [转]socket使用TCP协议时,send、recv函数解析以及TCP连接关闭的问题

    Tcp协议本身是可靠的,并不等于应用程序用tcp发送数据就一定是可靠的.不管是否阻塞,send发送的大小,并不代表对端recv到多少的数据. 在阻塞模式下, send函数的过程是将应用程序请求发送的数 ...

  9. linux recv函数返回值分析

    函数原型: ssize_t recv(int sockfd, void *buf, size_t len, int flags); 该函数第一个参数制定接收端套接字描述符; 第二个参数指明一个缓冲区, ...

随机推荐

  1. 2017-7-18-每日博客-关于Linux下的history的常用命令.doc

    History history命令可以用来显示曾执行过的命令.执行过的命令默认存储在HOME目录中的.bash_history文件中,可以通过查看该文件来获取执行命令的历史记录.需要注意的是.bash ...

  2. How to speed up insertion performance in PostgreSQL

    Disable any triggers on the table Drop indexes before starting the import, re-create them afterwards ...

  3. POJ 2112 二分+最大流

    Optimal Milking Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 17297   Accepted: 6203 ...

  4. Bigbluebutton服务执行过程及相关配置文件

    BigBlueButton服务列表 BigBlueButton由许多开源的服务组成,看似很麻烦,实际上拆分开每一个服务就很简单了,组件化平台化.究竟BBB都用到了哪些开源服务?我们来列举一下,名称均带 ...

  5. CMDB资产管理系统开发【day27】:cmdb API安全认证

    1.API验证分析 API三关验证 客户端和服务端中都存放一份相同的随机字符串,客户端发请求的时候把随机字符串和当前时间进行MD5加密,同时带着当前时间通过请求头发送到API,进入三关验证. 第一关是 ...

  6. Sass 基本函数

    Sass 中的常用函数 一.字符串函数 1. unquote($string): 删除字符串前后的引号,删除一对引号,如果这个字符串没有带有引号,将返回原始的字符串. 示例: .text1 { con ...

  7. 安装在Linux下的jenkins执行windows下的bat命令

    launch method里面没有 launch agent via java web start 默认是disable 需要改成random 转载自: http://blog.csdn.net/so ...

  8. [uva11174]村民排队 递推+组合数+线性求逆元

    n(n<=40000)个村民排成一列,每个人不能排在自己父亲的前面,有些人的父亲不一定在.问有多少种方案. 父子关系组成一个森林,加一个虚拟根rt,转化成一棵树. 假设f[i]表示以i为根的子树 ...

  9. 12.13记录//QQDemo示例程序源代码

            笔记的完整版pdf文档下载地址: https://www.evernote.com/shard/s227/sh/ac692160-68c7-4149-83ea-0db5385e28b0 ...

  10. ios的app,有新版本时必须先更新。

    现在没时间整理,先把代码贴出来,以后再做详细的思路整理. 1 在AppController.mm的didFinishLaunchingWithOptions方法里面获取本地应用版本信息,保存起来. / ...