swoole--异步websocket服务端

2021-05-21
use Swoole\WebSocket\Server;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\WebSocket\Frame;

$server = new Server("0.0.0.0", 9501);

$server->set([
    'websocket_subprotocol' => 'chat', //设置WebSocket子协议。设置后握手响应的HTTP头会增加Sec-WebSocket-Protocol: {$websocket_subprotocol}。具体使用方法请参考WebSocket协议相关RFC文档。
    'websocket_compression' => true,//启用数据压缩,true允许对帧进行zlib压缩,是否能够压缩取决于客户端是否能够处理压缩,需要配合flags参数SWOOLE_WEBSOCKET_FLAG_COMPRESS来真正地对具体的某个帧进行压缩
]);

// 客户端连接服务端并完成握手后的回调;$request是一个HTTP请求对象,包含了客户端发来的握手请求信息
$server->on('open', function (Server $server, Request $request) {
    echo "server: handshake success with fd{$request->fd}\n";
});


// 客户端发送消息时的回调;$frame 包含了客户端发来的数据帧信息
$server->on('message', function (Server $server, Frame $frame) {
	if ($frame->opcode === WEBSOCKET_OPCODE_PING) { // 如果接收到ping帧返回pong帧保持长连接
		$pingFrame = new Frame;
		$pingFrame->opcode = WEBSOCKET_OPCODE_PONG;
		$server->push($frame->fd, $pingFrame);
	} elseif (1 == 2) { // 在指定情况下主动关闭客户端连接
		// 关闭客户端连接并发送关闭原因$reason,$reason不能超过125字节,失败返回false
		$server->disconnect($frame->fd, $code = SWOOLE_WEBSOCKET_CLOSE_NORMAL, $reason = '');
	} else {	
		echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
		// 向客户端$fd推送数据$data,$data长度最大不得超过2M;$data类型$opcode可以是文本(WEBSOCKET_OPCODE_TEXT)/二进制(WEBSOCKET_OPCODE_BINARY)
		// $flags表示是否发送完成SWOOLE_WEBSOCKET_FLAG_FIN(1)(完成),可同时指定SWOOLE_WEBSOCKET_FLAG_COMPRESS(进行压缩)
		$server->push($frame->fd, $data = "this is server", $opcode = WEBSOCKET_OPCODE_TEXT, $flags = SWOOLE_WEBSOCKET_FLAG_FIN);
	}
});

// 收到一个完整的HTTP请求后,会回调此函数;设置此回调server可以同时用作HTTP服务器
$server->on('request', function (Request $request, Response $response) {
	if ($request->server['request_uri'] == 'WebSocket') {
		global $server;
		// 获取所有客户端连接数组,演示
		foreach($server->connections as $connection)
		{
			// 判断客户端连接是否存在
			if ($server->exist($connection->fd)) {
				// 检查连接是否为有效的WebSocket客户端连接
				if ($server->isEstablished($connection->fd)) {
					// 打包WebSocket消息$data;$data类型$opcode可以是文本(WEBSOCKET_OPCODE_TEXT)/二进制(WEBSOCKET_OPCODE_BINARY)
					// $flags表示是否发送完成SWOOLE_WEBSOCKET_FLAG_FIN(1)(完成),可同时指定SWOOLE_WEBSOCKET_FLAG_COMPRESS(进行压缩)
					$data = Server::pack($data = 'websocket data', $opcode = WEBSOCKET_OPCODE_TEXT, $flags = SWOOLE_WEBSOCKET_FLAG_FIN);
					$server->send($connection->fd, $data);
				}
			}
		}
	} else {
		echo "http request\n";
	}
});

// 客户端关闭连接时回调
$server->on('close', function (Server $server, $fd) {
    echo "client {$fd} closed\n";
});

$server->start();

 

 

{/if}