swoole--协程WEBSOCKET服务器

2021-05-23

完全协程化的WebSocket服务器实现,继承自Coroutine\Http\Server,底层提供了对WebSocket协议的支持

示例

use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\WebSocket\CloseFrame;
use Swoole\Coroutine\Http\Server;
use function Swoole\Coroutine\run;

run(function () {
    $server = new Server('127.0.0.1', 9502, false);
    $server->handle('/websocket', function (Request $request, Response $ws) {
        // 向客户端发送WebSocket握手消息
        $ws->upgrade();

        global $wsObjects;
        $objectId = spl_object_id($ws);
        $wsObjects[$objectId] = $ws;

        while (true) {
            // 接收WebSocket消息帧,返回Swoole\WebSocket\Frame对象,失败返回false,接收超时间为$timeout
            $frame = $ws->recv($timeout = -1);
            if ($frame === '') {
                unset($wsObjects[$objectId]);
                $ws->close();
                break;
            } else if ($frame === false) {
                echo 'errorCode: ' . swoole_last_error() . "\n";
                // 关闭连接
                $ws->close();
                break;
            } else {
                if ($frame->data == 'close' || get_class($frame) === CloseFrame::class) {
                    unset($wsObjects[$objectId]);
                    $ws->close();
                    break;
                }
                // 向对端发送数据帧$data,$opcode为数据内容格式WEBSOCKET_OPCODE_TEXT、WEBSOCKET_OPCODE_BINARY,$finish为true表示数据发送完成
                // $data为Swoole\WebSocket\Frame对象时后续参数会被忽略
                // $ws->push(string|object $data, int $opcode = 1, bool $finish = true);
                $ws->push("Hello {$frame->data}!");
                
                // 群发数据
                foreach ($wsObjects as $obj) {
                    $obj->push("Server:{$frame->data}");
                }
            }
        }
    });

    // 同时支持启用HTTP服务
    $server->handle('/', function (Request $request, Response $response) {
        $response->end(<<<HTML
		    <h1>Swoole WebSocket Server</h1>
		    <script>
				var wsServer = 'ws://127.0.0.1:9502/websocket';
				var websocket = new WebSocket(wsServer);
				websocket.onopen = function (evt) {
				    console.log("Connected to WebSocket server.");
				    websocket.send('hello');
				};

				websocket.onclose = function (evt) {
				    console.log("Disconnected");
				};

				websocket.onmessage = function (evt) {
				    console.log('Retrieved data from server: ' + evt.data);
				};

				websocket.onerror = function (evt, e) {
				    console.log('Error occured: ' + evt.data);
				};
			</script>
			HTML
        );
    });

    $server->start();
});

 

{/if}