| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 | <?phpnamespace GatewayClient;/** * This file is part of workerman. * * Licensed under The MIT License * For full copyright and license information, please see the MIT-LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @author walkor<walkor@workerman.net> * @copyright walkor<walkor@workerman.net> * @link http://www.workerman.net/ * @license http://www.opensource.org/licenses/mit-license.php MIT License *//** * Gateway 与 Worker 间通讯的二进制协议 * * struct GatewayProtocol * { *     unsigned int        pack_len, *     unsigned char       cmd,//命令字 *     unsigned int        local_ip, *     unsigned short      local_port, *     unsigned int        client_ip, *     unsigned short      client_port, *     unsigned int        connection_id, *     unsigned char       flag, *     unsigned short      gateway_port, *     unsigned int        ext_len, *     char[ext_len]       ext_data, *     char[pack_length-HEAD_LEN] body//包体 * } * NCNnNnNCnN */class GatewayProtocol{    // 发给worker,gateway有一个新的连接    const CMD_ON_CONNECT = 1;    // 发给worker的,客户端有消息    const CMD_ON_MESSAGE = 3;    // 发给worker上的关闭链接事件    const CMD_ON_CLOSE = 4;    // 发给gateway的向单个用户发送数据    const CMD_SEND_TO_ONE = 5;    // 发给gateway的向所有用户发送数据    const CMD_SEND_TO_ALL = 6;    // 发给gateway的踢出用户    // 1、如果有待发消息,将在发送完后立即销毁用户连接    // 2、如果无待发消息,将立即销毁用户连接    const CMD_KICK = 7;    // 发给gateway的立即销毁用户连接    const CMD_DESTROY = 8;    // 发给gateway,通知用户session更新    const CMD_UPDATE_SESSION = 9;    // 获取在线状态    const CMD_GET_ALL_CLIENT_SESSIONS = 10;    // 判断是否在线    const CMD_IS_ONLINE = 11;    // client_id绑定到uid    const CMD_BIND_UID = 12;    // 解绑    const CMD_UNBIND_UID = 13;    // 向uid发送数据    const CMD_SEND_TO_UID = 14;    // 根据uid获取绑定的clientid    const CMD_GET_CLIENT_ID_BY_UID = 15;    // 批量获取uid列表批量获取绑定的clientid    const CMD_BATCH_GET_CLIENT_ID_BY_UID = 16;    // 加入组    const CMD_JOIN_GROUP = 20;    // 离开组    const CMD_LEAVE_GROUP = 21;    // 向组成员发消息    const CMD_SEND_TO_GROUP = 22;    // 获取组成员    const CMD_GET_CLIENT_SESSIONS_BY_GROUP = 23;    // 获取组在线连接数    const CMD_GET_CLIENT_COUNT_BY_GROUP = 24;    // 按照条件查找    const CMD_SELECT = 25;    // 获取在线的群组ID    const CMD_GET_GROUP_ID_LIST = 26;    // 取消分组    const CMD_UNGROUP = 27;    // worker连接gateway事件    const CMD_WORKER_CONNECT = 200;    // 心跳    const CMD_PING = 201;    // GatewayClient连接gateway事件    const CMD_GATEWAY_CLIENT_CONNECT = 202;    // 根据client_id获取session    const CMD_GET_SESSION_BY_CLIENT_ID = 203;    // 发给gateway,覆盖session    const CMD_SET_SESSION = 204;    // 当websocket握手时触发,只有websocket协议支持此命令字    const CMD_ON_WEBSOCKET_CONNECT = 205;    // 包体是标量    const FLAG_BODY_IS_SCALAR = 0x01;    // 通知gateway在send时不调用协议encode方法,在广播组播时提升性能    const FLAG_NOT_CALL_ENCODE = 0x02;    /**     * 包头长度     *     * @var int     */    const HEAD_LEN = 28;    public static $empty = array(        'cmd'           => 0,        'local_ip'      => 0,        'local_port'    => 0,        'client_ip'     => 0,        'client_port'   => 0,        'connection_id' => 0,        'flag'          => 0,        'gateway_port'  => 0,        'ext_data'      => '',        'body'          => '',    );    /**     * 返回包长度     *     * @param string $buffer     * @return int return current package length     */    public static function input($buffer)    {        if (strlen($buffer) < self::HEAD_LEN) {            return 0;        }        $data = unpack("Npack_len", $buffer);        return $data['pack_len'];    }    /**     * 获取整个包的 buffer     *     * @param mixed $data     * @return string     */    public static function encode($data)    {        $flag = (int)is_scalar($data['body']);        if (!$flag) {            $data['body'] = serialize($data['body']);        }        $data['flag'] |= $flag;        $ext_len      = strlen($data['ext_data']);        $package_len  = self::HEAD_LEN + $ext_len + strlen($data['body']);        return pack("NCNnNnNCnN", $package_len,                $data['cmd'], $data['local_ip'],                $data['local_port'], $data['client_ip'],                $data['client_port'], $data['connection_id'],                $data['flag'], $data['gateway_port'],                $ext_len) . $data['ext_data'] . $data['body'];    }    /**     * 从二进制数据转换为数组     *     * @param string $buffer     * @return array     */    public static function decode($buffer)    {        $data = unpack("Npack_len/Ccmd/Nlocal_ip/nlocal_port/Nclient_ip/nclient_port/Nconnection_id/Cflag/ngateway_port/Next_len",            $buffer);        if ($data['ext_len'] > 0) {            $data['ext_data'] = substr($buffer, self::HEAD_LEN, $data['ext_len']);            if ($data['flag'] & self::FLAG_BODY_IS_SCALAR) {                $data['body'] = substr($buffer, self::HEAD_LEN + $data['ext_len']);            } else {                $data['body'] = unserialize(substr($buffer, self::HEAD_LEN + $data['ext_len']));            }        } else {            $data['ext_data'] = '';            if ($data['flag'] & self::FLAG_BODY_IS_SCALAR) {                $data['body'] = substr($buffer, self::HEAD_LEN);            } else {                $data['body'] = unserialize(substr($buffer, self::HEAD_LEN));            }        }        return $data;    }}
 |