tcp粘包问题补充

上篇文章

提到阻塞(block)一下如何read数据

这里针对是非阻塞如何read数据

并且纠正前面出现几个错误

(1) 非阻塞 遇到errno=EAGAIN必须continue处理 ,epoll_wait 下次还能触发吗?

(2) 服务器read一次数据 ,只解析一个包的数据

会不会出现每次客户端发送新数据 但是服务器读取仍然是历史发送记录,

缓存里留着未处理数据情况

在一个异步非阻塞的socket上调用read/write函数读为2个步骤

  • 步骤1 调用read从系统 层读取到应用层
  • 步骤2 解析数据

01

步骤1 调用read从系统buffer读取到应用层buffer

epoll提供两种工作模式:LT和ET Level-Triggered and Edge-Triggered

区别是:

  • 前者触发多次,下次触发条件:

只 要缓冲区有数据,不区分是上次未读取还是新来的

  • 后者只 触发一次 下次触发条件:

1 有新的数据写入管道 缓冲区有数据 (consume the whole buffer data)

2 遇到EAGAIN (return EAGAIN)

3 缓冲区有数据但是属于上次遗留的 不触发

参考 man epoll 例子

  • 如果是ET模式,管道中剩余的1KB被挂起,再次调用epoll_wait,得不到管道读者的文件句柄,除 非有新的数据写入管道
  • 如果是LT模式,只要管道中有数据可读,每次调用epoll_wait都会触发。

//所以,在epoll的ET模式下,正确的读写方式为:

读:只要可读,就一直读,直到返回0,或者 errno = EAGAIN(break 满足下次触发条件)

写:只要可写,就一直写,直到数据发送完,或者 errno = EAGAIN(break 满足下次触发条件)

在epoll的LT模式下相反

读:忽略掉errno = EAGAIN的错误,下次继续读 continue

写:忽略掉errno = EAGAIN的错误,下次继续写

ET

02

步骤2 解析数据

说明: 这里约定数据包是指是客户端发送一次的数据

应用层 利用socket从系统底层缓冲区(buffer)read一次n字节大小数据到本地buffer

这些数据

可能客户端发送数据过大一个包拆拆分多个包发送,

也可能数据过小

多个包合并成一个包发送,

也可能就是客户端连续发送多次

解析n字节大小数据 步骤

1 小于一个包 俗称半包

判断bytebuffer中剩余数据是否足够一个包,不够继续系统缓冲区读取 IO操作

2 完整的一个包

读取一个包之后,剩余数据为零继续等待客户端下一个请求IO操作

3 包涵:多个包

继续解析,知道满足条件1和2为止

解包

关于同步和异步后面在详细说明

  • blocking I/O
  • nonblocking I/O
  • I/O multiplexing (select and poll)
  • signal driven I/O (SIGIO)
  • asynchronous I/O (the POSIX aio_functions)

io

本章节内容:

socket之send与发送缓冲区大小的没有任何关系 主要原因是发送缓冲区大小和接受缓冲大小可以设置任意数值 造成了这 一个数据包被多次接受才算完整 异步非阻塞的socket上调用read/write函数读为2个步骤 步骤1 如何读取数据,注意是遇到错误该如何处理 步骤2:如何处理这些数据,注意黏合包,半包如何处理

下章预告:

大纲

这次提到tcp数据流无边界特点

还有一个特点那就是 TCP协议中有长连接和短连接之分

需要心跳包传统的 keepAlive有什么缺点,为什么非要自己实现

计划:

plan

喜欢

分享

or

相关推荐:

原文发布于微信公众号 - 架构说(JiaGouS)

原文发表时间:2017-12-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏DeveWork

WordPress 显示数据库查询次数、查询时间及内存占用的代码

如果对进行过WordPress 性能优化,需要一个直观简单的查看方式的话,那么就可以使用下面所提及的代码,通过这段代码,可以在直观或者在html 源代码查看数据...

211100
来自专栏牛客网

Linux入门学习笔记

1. 指令、选项或参数之间不论空几个格, shell 都视为一个空格。 2. 指令太长时,可以使用“ \ ”(反斜杠)符号使指令连续到下一行。 3. Linux...

441100
来自专栏DannyHoo的专栏

禁止子视图响应父视图的点击事件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010105969/article/details/...

19210
来自专栏我是攻城师

最近工作中遇到ElasticSearch一些问题总结

618100
来自专栏Java技术栈

前后端分离与不分离的本质区别!

在前后端不分离的应用模式中,前端页面看到的效果都是由后端控制,由后端渲染页面或重定向,也就是后端需要控制前端的展示,前端与后端的耦合度很高。

8310
来自专栏章鱼的慢慢技术路

在Linux下使用gcc编译mesa文件报undefined reference to symbol 'sin@@GLIBC_2.2.5和DSO missing from command line两个

在Ubuntu下安装好mesa所需的库文件,将目标文件从github上克隆下来之后编译。

13310
来自专栏蓝天

MOOON-server新消息处理接口

    MOOON-server提供了一个通用的TCP框架,并对包的解析抽象出了IPacketHandler接口,这个接口提供了无限制的宽容度,支持任何协议,但...

9420
来自专栏C/C++基础

Linux下使用gdb调试core文件

当程序运行过程中出现Segmentation fault (core dumped)错误时,程序停止运行,并产生core文件。core文件是程序运行状态的内存映...

28430
来自专栏抠抠空间

Linux用户权限

18800
来自专栏Java架构沉思录

一文读懂分布式Session常见解决方案

前言 沉思君在之前的文章《谈谈HTTP状态保持》里介绍了有关HTTP状态保持的知识点,我们知道HTTP协议本身是无状态的,因此在使用HTTP协议进行通信的过程中...

28780

扫码关注云+社区

领取腾讯云代金券