forked from walkor/workerman
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGatewayProtocol.php
161 lines (142 loc) · 4.36 KB
/
GatewayProtocol.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<?php
/**
* 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<[email protected]>
* @copyright walkor<[email protected]>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Workerman\Protocols;
/**
* 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 client_id,
* unsigned char flag,
* unsigned int ext_len,
* char[ext_len] ext_data,
* char[pack_length-HEAD_LEN] body//包体
* }
*
*/
class GatewayProtocol
{
// 发给worker,gateway有一个新的连接
const CMD_ON_CONNECTION = 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的踢出用户
const CMD_KICK = 7;
// 发给gateway,通知用户session更改
const CMD_UPDATE_SESSION = 9;
// 获取在线状态
const CMD_GET_ONLINE_STATUS = 10;
// 判断是否在线
const CMD_IS_ONLINE = 11;
// 包体是标量
const FLAG_BODY_IS_SCALAR = 0x01;
/**
* 包头长度
* @var integer
*/
const HEAD_LEN = 26;
public static $empty = array(
'cmd' => 0,
'local_ip' => '0.0.0.0',
'local_port' => 0,
'client_ip' => '0.0.0.0',
'client_port' => 0,
'client_id' => 0,
'flag' => 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 array $data
* @return string
*/
public static function encode($data)
{
$flag = (int)is_scalar($data['body']);
if(!$flag)
{
$data['body'] = serialize($data['body']);
}
$ext_len = strlen($data['ext_data']);
$package_len = self::HEAD_LEN + $ext_len + strlen($data['body']);
return pack("NCNnNnNNC", $package_len,
$data['cmd'], ip2long($data['local_ip']),
$data['local_port'], ip2long($data['client_ip']),
$data['client_port'], $data['client_id'],
$ext_len, $flag) . $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/Nclient_id/Next_len/Cflag", $buffer);
$data['local_ip'] = long2ip($data['local_ip']);
$data['client_ip'] = long2ip($data['client_ip']);
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;
}
}