一、成员变量
包含以下成员变量:
//各种帧类型的常量 const FRAME_CONTINUE = 0x00; const FRAME_TEXT = 0x01; const FRAME_BIN = 0x02; const FRAME_CLOSE = 0x08; const FRAME_PING = 0x09; const FRAME_PONG = 0x0A; protected $serverSocket = null;//服务器监听的socket protected $shutdown = false;//关闭状态,如果是true表示服务器准备关闭 protected $socketList = array();//保存所有socket的数组 protected $socketListMap = array();//根据唯一id对socket进行索引,并保存socket的其他自定义属性,相当于session private $handshakingList = array();//正在进行握手的socket,用于处理握手超时的socket private $lastHealthCheck = null;//最后一次进行健康检查的时间,这里根据最后一次通信时间判断健康状态,检查时默认不会发送pong帧 private $healthCheckInterval = 300;//健康检查间隔,单位秒,每次处理完一个连接后会判断是否进行健康检查。 private $handshakeTimeout = 10;//握手超时时间,单位秒,为了防止过多的未完成握手占用系统资源,会对超时的握手连接进行关闭处理。
二、构造函数与析构函数
//port监听的端口号,address监听的IP地址,0.0.0.0表示监听本机上任何地址,debug为调试开关,为true是会打印错误信息及其他信息。 function __construct($port, $address = '0.0.0.0', $debug = false) { $this->serverSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_option($this->serverSocket, SOL_SOCKET, SO_REUSEADDR, 1); socket_set_option($this->serverSocket, SOL_SOCKET, TCP_NODELAY, 1); //socket绑定 if (socket_bind($this->serverSocket, $address, $port) === false) { if ($debug) { echo $this->getLastErrMsg(); } return; } //监听开始 if (socket_listen($this->serverSocket) === false) { if ($debug) { echo $this->getLastErrMsg(); } return; } $this->onstarted($this->serverSocket); $this->lastHealthCheck = time(); $this->run(); } function __destruct() { socket_close($this->serverSocket); }
三、WebSocket类方法
//主工作函数,控制整体流程 function run(){} //服务启动后回调 function onstarted($serverSocket){} //socket连接后回调 function onconnected($socket){} //收到不完整的握手包时回调 function onUpgradePartReceive($socketId){} //握手失败后回调 function onHandShakeFailure($socketId){} //握手成功后回调 function onHandShakeSuccess($socketId){} //断开连接时回调 function ondisconnected($socketId){} //从列表中移除socket时回调 function onAfterRemoveSocket($socketId){} //健康检查后回调 function onafterhealthcheck($unhealthyList){} //遇到socket错误时回调 function onerror($errCode, $socketId){} //服务器关闭时回调 function onshutdown(){} //健康检查函数 function healthCheck(){} //业务逻辑处理函数(应由继承类覆盖实现) function businessHandler($socketId){} //帧是否结束 function isFin($byte){} //帧是否进行掩码处理 function isMasked($byte){} //获取帧类型 function getFrameType($byte){} //处理任意类型的帧 function parseRawFrame($payload, $mask){} //处理文本帧 function parseTextFrame($payload, $mask){} //处理二进制帧 function parseBinaryFrame($payload, $mask){} //创建关闭帧,支持关闭码及关闭原因 function closeFrame($socketId, $closeCode = 1000, $closeMsg = 'goodbye'){} //发送ping帧 function sendPing($socketId, $data = 'ping'){} //发送pong帧 function sendPong($socketId, $data = 'pong'){} //获取掩码 function getMask($data, $len){} //获取数据负载 function getPayload($data, $len){} //获取负载长度 function getPayloadLen($data){} //判断是否为控制帧 function isControlFrame($frameType){} //解析帧 function parseFrame($data, $socketId){} //创建指定类型的帧,支持分帧 function createFrame($data, $type, $fin = 0x01){} //计算WebSocket-Accept值 function getWebSocketAccept($websocketKey){} //协议选择(协商),建议继承后通过覆盖自定义 function selectProtocol($protocols){} //获取握手响应头 function getHandShakeHeader($headers){} //基础协议头检查,只检查WebSocket协议要求的请求头字段 function checkBaseHeader($header){} //用户自定义头检查,如cookie等信息检查,需要覆盖此方法实现,该处返回恒为true function checkCustomHeader($header){} //创建握手失败的响应 function badRequest($socketId){} //获取响应头的各个字段 function getHeaders($header){} //移除握手超时的连接 function removeUnhandshakeConnect(){} //WebSocket握手 function doHandShake($socketId){} //显示数据信息,仅调试使用 function showData($buffer){} //发送数据 function sendData($socketId, $data, $type = self::FRAME_TEXT, $isFin = true){} //根据socket获取socketId function getSocketId($socket){} //添加socket到列表中 function addSocket($socket){} //从列表中移除socket function removeSocket($socketId){} //关闭服务器 function shutdown(){} //接受Socket function socketAccept(){} //从socket中读数据 function socketRecv($socketId){} //通过socket写数据 function socketSend($socketId, $data){} //关闭底层socket function socketClose($socketId){} //连接socket操作 function connect($socket){} //通过socket断开连接 function disconnectBySocket($socket){} //通过socketId断开连接 function disconnect($socketId, $silent = false){} //获取错误码 function getLastErrCode($socketId = null){} //获取错误详情 function getLastErrMsg($socketId = null, $errCode = null){}
后面的文章将具体介绍每个函数的实现。