-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathChatServer.php
151 lines (134 loc) · 5.06 KB
/
ChatServer.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
<?php
/**
* Created by PhpStorm.
* User: ullone
* Date: 2019/2/18
* Time: 18:44
*/
namespace console\extend\chat_im;
use console\extend\chat_im\model\ChatUser;
use \Swoole\WebSocket\Server as SwooleSocketServer;
use Yii;
class ChatServer
{
private $port = '9501';//聊天室服务端口
private $server;
public function __construct()
{
$this->server = new SwooleSocketServer("0.0.0.0",$this->port, SWOOLE_PROCESS , SWOOLE_SOCK_TCP | SWOOLE_SSL);
$this->server->set([
'reactor_num' => Yii::$app->params['swoole']['reactor_num'],
'worker_num' => Yii::$app->params['swoole']['worker_num'],
'max_request' => Yii::$app->params['swoole']['max_request'],
//'chroot' => '/var/www/yiia/console',
'user' => Yii::$app->params['swoole']['user'],
'group' => Yii::$app->params['swoole']['group'],
'ssl_cert_file' => Yii::$app->params['swoole']['ssl_cert_file'],
'ssl_key_file' => Yii::$app->params['swoole']['ssl_key_file'],
]);
}
/**
* 监听握手处理
*/
public function handshake()
{
$this->server->on('handshake', function (\swoole_http_request $request, \swoole_http_response $response) {
echo '接收到一条连接握手请求.' . PHP_EOL;
// 验证身份,如果验证未通过end输出,返回false,握手失败,拒绝连接
if(!ChatUser::checkIdentity($request)){
$response->end();
return false;
}
// websocket握手连接算法验证
$secWebSocketKey = $request->header['sec-websocket-key'];
$patten = '#^[+/0-9A-Za-z]{21}[AQgw]==$#';
if (0 === preg_match($patten, $secWebSocketKey) || 16 !== strlen(base64_decode($secWebSocketKey))) {
$response->end();
return false;
}
$key = base64_encode(sha1(
$request->header['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
true
));
$headers = [
'Upgrade' => 'websocket',
'Connection' => 'Upgrade',
'Sec-WebSocket-Accept' => $key,
'Sec-WebSocket-Version' => '13',
];
// WebSocket connection to 'ws://127.0.0.1:9502/'
// failed: Error during WebSocket handshake:
// Response must not include 'Sec-WebSocket-Protocol' header if not present in request: websocket
if (isset($request->header['sec-websocket-protocol'])) {
$headers['Sec-WebSocket-Protocol'] = $request->header['sec-websocket-protocol'];
}
foreach ($headers as $key => $val) {
$response->header($key, $val);
}
$response->status(101);
$response->end();
});
}
/**
* 开启服务器
*/
public function start(){
$this->server->start();
}
/**
* 监听WebSocket连接打开事件
*/
public function open()
{
echo '监听连接...'.PHP_EOL;
$this->server->on('open', function (SwooleSocketServer $server, $request) {
// if($server->disconnect($request->fd, 1000,'非法连接!')){
// echo "非法接入,已断开连接:{$request->fd}".PHP_EOL;
// return false;
// }
echo "成功连接到聊天室 fd:{$request->fd}".PHP_EOL;
});
}
/**
* 监听WebSocket消息事件
*/
public function message()
{
$this->server->on('message', function (SwooleSocketServer $server, $frame) {
// $this->server->connections 所有websocket连接用户的fd
// 消息处理,返回相关用户的fds和返回信息
$response = HandleAction::getInstance()->handle($frame);
foreach ($this->server->connections as $fd) {
if(in_array($fd,$response->fds)){
echo "推送消息给fd:{$fd}".PHP_EOL;
$this->server->push($fd,json_encode($response->msg,JSON_UNESCAPED_UNICODE));
}
}
});
}
/**
* 监听WebSocket连接关闭事件
*/
public function close()
{
$this->server->on('close', function ($ser, $fd) {
echo "client {$fd} closed\n";
HandleAction::getInstance()->destroy($fd);
});
}
/**
* 监听WebSocket http请求事件
*/
public function request(){
echo '监听请求...'.PHP_EOL;
$this->server->on('request', function ($request, $response) {
echo '接收到一个请求.'.PHP_EOL;
// 接收http请求从get获取message参数的值,给用户推送
// $this->server->connections 遍历所有websocket连接用户的fd,给所有用户推送
// foreach ($this->server->connections as $fd) {
// echo $request->get['message'].' to fd:'.$fd;
// $this->server->push($fd, $request->get['message']);
// }
});
}
}