swoole项目开发思惟转换 -- 粘包

swoole是用php快速开发高效的tcp/udp服务, 其中tcp是用的更多的一个场景,http虽然是基于tcp协议的,但和直接开发tcp服务仍是有明显的区别的。php

TCP是数据流前端

tcp是数据流,这是一个基本的概念,这里有两个要点:web

  1. 数据没有边界编程

    你能够理解为水在一个水管里的流动,咱们不知道哪段数据是一个咱们须要的完整数据数组

  2. 收发有缓冲区服务器

    好比:当水从一端流到了另外一端,咱们在收数据的时候,不可能每来一滴水就处理一次,这个缓冲区就至关于有了一个水桶,再接了必定的水以后内核再给数据交到用户空间,这样能够大大提高性能。swoole

那这里就有一个问题:因为这个特性,内核没法知道哪部分数据是你想要的,因此应用层拿到数据多是完整数据,也多是不完整或者一部分完整、一部分不完整(粘包),那么怎样能获得想要的数据呢?
网络

数据协议tcp

数据协议能够理解为一种约定,按照这个约定来处理收到的数据进而获得想要的数据,这个过程就称为拆包,那问题又来了?性能

web开发为何不用考虑粘包

由于web的http能够理解为一个公共的数据协议,在实现一个web服务器的时候,就必需按照这个协议来进行数据处理,这样保证在应用层获取到数据是完整的数据,http是典型的包头+包体的这个一个约定格式,有那现几个特色:

  1. 经过\r\n\r\n来区分包头和包体

  2. 包头经过\r\n来区分不一样的数据组

看个示例:

GET / HTTP/1.1

Host: www.swoole.com

Connection: keep-alive

这是一个典型的请求头,第一行约定了请求的方法(GET/POST/PUT/DELETE等)、请求地址、http协议版本, 从第二行开始,都是健:值的形式,反应到PHP里,就是$_SERVER超全局变里里 HTTP_开头的数据,因为这是GET请求,全部没有包体,若是是POST或者response响应,咱们能够看到包体,包体的长度经过包头里的Content-Length参数来控制的

Swoole怎么处理粘包

swoole考虑到在粘包是一个必需处理的过程,内置了两种方案:

  1. 约定结束符

    这个相似于c里面的字符串数组,约定了\0表示字符串结束,在swoole里,能够的setting数组中,开启open_eof_check=true,并用package_eof来设置一个完整数据结尾字符。

    举个例子:

    "open_eof_check"=>true

    "package_eof" = >'swooleend',


    这里设置了package_eof = 'swooleend', 那client在每一个完整数据以后再拼上swooleend以后,再发送到swoole server,swoole server就能自动识别并拼出一个完整的包。这里又隐含了两个小问题?

    a)  若是我一次收到了多个完整包怎么办?

            那能够开启 open_eof_split=>true, 这样在onReceive里回调里拿到的数据就是一个完整的包了,不然须要业务层里自行explode('swooleend', $data)了,

    b)  要保证业务数据里不能出现package_eof设置的字符,不然将致使数据错误了。


  2. 自定义包头包体

    这种方式也很常见,特别是在二进制数据流中,原理是经过约定数据流的前几个字节来表示一个完整的数据有多长,从第一个数据到达以后,先经过读取固定的几个字节,解出数据包的长度,而后按这个长度继续取出后面的数据,依次循环。

    相关配置:

        'package_length_type'   => 'N',      //数据unpack方式,这里N表示无符号32位大端长整型,更多定义能够参考:http://php.net/manual/zh/function.pack.php

        'package_length_offset'=> 0,       //第N个字节是包长度的值

        'package_body_offset'   => 4,       //第几个字节开始计算长度

        'package_max_length'    => 2000000,  //协议最大长度


    这个配置表示,前端4个字节是数据包长度,按照N的方式解析,最后一个配置表示数据包的最大长度,这个配置的目的是为了控制内存。


    总结,粘包处理是不少新作服务器网络编程最容易碰到的问题,特别是长期作web开发的同窗,基本没有这个概念,因此经过这个思惟转换,更深刻的了解http协议,进而了解tcp协议,对服务器网络编程是很是有好处的。

    相关文章
    相关标签/搜索