短连接|长连接
在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web资源(如JavaScript文件、图像文件、CSS文件等),每遇到这样一个Web资源,浏览器就会重新建立一个HTTP会话。
而从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入这行代码:Connection:keep-alive
在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。
HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。
事例:短连接:web网页 ajax http 长连接 :qq聊天 ,直播 ,rpc(远程控制软件)
swoole_get_local_ip()
此函数用于获取本机所有网络接口的 IP 地址
// 获取本机所有网络接口的IP地址$list = swoole_get_local_ip();print_r($list);
返回值
Array(
[eno1] => 10.10.28.228
[br-1e72ecd47449] => 172.20.0.1
[docker0] => 172.17.0.1
)
健康检查
保持客户端会话的有效性健康平台客户端的忘了状态,使用了健康检查,两种实现方式:轮询机制,心跳机制
轮询机制:服务端定时请求客户端 是否还在链接
心跳机制:客户端定时发送请求到服务器端,一般使用该机制
daemonize 守护进程化【默认值:0】
设置 daemonize => 1 时,程序将转入后台作为守护进程运行。长时间运行的服务器端程序必须启用此项。
如果不启用守护进程,当 ssh 终端退出后,程序将被终止运行。
heartbeat_check_interval 启用心跳检测【默认值:false】
此选项表示每隔多久轮循一次,单位为秒。如 heartbeat_check_interval => 60,表示每 60 秒,遍历所有连接,如果该连接在 120 秒内(heartbeat_idle_time 未设置时默认为 interval 的两倍),没有向服务器发送任何数据,此连接将被强制关闭。若未配置,则不会启用心跳,该配置默认关闭,heartbeat_check 仅支持 TCP 连接
heartbeat_idle_time连接最大允许空闲的时间
需要与 heartbeat_check_interval 配合使用
array(
'heartbeat_idle_time'=>600,// 表示一个连接如果600秒内未向服务器发送任何数据,此连接将被强制关闭
'heartbeat_check_interval'=>60,// 表示每60秒遍历一次);
每个60秒遍历一次是否有长连接在进行,如果600秒内没有发送过数据将关闭长连接
提示
启用 heartbeat_idle_time 后,服务器并不会主动向客户端发送数据包
如果只设置了 heartbeat_idle_time 未设置 heartbeat_check_interval 底层将不会创建心跳检测线程,PHP 代码中可以调用 heartbeat 方法手工处理超时的连接
TCP的链接和断开链接
tcp的三次链接握手:第一次客户端发送请求询问是否可用链接
第二次服务器发送可用请求的通知
第三次客户端发送请求数据
tcp断开链接的四次挥手:第一次发送请求断开
第二次服务器针对客户端的请求确认回答
第三次服务器发送断开链接请求
第四次客户端针对服务器的断开请求确认回答
粘包问题解决方案
原因:tcp在数据传输时,以字节流的行书传输,并且会有tcp缓存形式每隔一段时间或者每隔一段字节发送一次数据,则会出现上次发送的数据和本次发送的数据,以一个数据包的形式发送到服务器,造成客户端以多次发送数据,单服务器接受以一次数据包接受
解决方案
1 特殊字符:根据客户端和服务器相互约定的特殊符号,对接受的数据进行分割处理
open_eof_check 打开 EOF 检测【默认值:false】, TCP 粘包问题
此选项将检测客户端连接发来的数据,当数据包结尾是指定的字符串时才会投递给 Worker 进程。否则会一直拼接数据包,直到超过缓存区或者超时才会中止。当出错时底层会认为是恶意连接,丢弃数据并强制关闭连接。
常见的 Memcache/SMTP/POP 等协议都是以 \r\n 结束的,就可以使用此配置。开启后可以保证 Worker 进程一次性总是收到一个或者多个完整的数据包。
array('open_eof_check'=>true,//打开EOF检测'package_eof'=>"\r\n",//设置EOF)
//在每个包的后面追加一个\r\n 在服务器端接受到数据后,通过explain方法 截取字符串为数组为每次发送的数据
2 固定包头+包体协议(主流) :通过与数据传输之后,在tcp数据包中了携带数据的长度然后,在服务器可以根据这个长度,对数据进行截取
pack ()打包 WebSocket 消息。
unpack()
客户端:
$content ="传输内容";
$len=pack('n',strlen($content));
$send =len.$content;
$client->send($send);
服务器端
$server->set(array( 'open_length_check' => true,
'package_max_length' => 81920,
'package_length_type' => 'n',
'package_length_offset' => 8,
'package_body_offset' => 16,));
$foolen=unpack("n",substr($data,0,2))[1];
$content =substr($data,2,$foolen)
open_length_check
打开包长检测特性【默认值:false】,参考 TCP 粘包问题
包长检测提供了固定包头 + 包体这种格式协议的解析。启用后,可以保证 Worker 进程 onReceive 每次都会收到一个完整的数据包。
长度检测协议,只需要计算一次长度,数据处理仅进行指针偏移,性能非常高