基于 Swoole 实现简单的 WebSocket 服务器及客户端
与 HTTP 类似,WebSocket 协议对应的 scheme 是 ws,如果是加密的 WebSocket 对应的 scheme 是 wss。
WebSocket 服务器 PHP 异步网络通信引擎 Swoole 内置了对 WebSocket 的支持,通过几行 PHP 代码就可以写出一个异步非阻塞多进程的 WebSocket 服务器:
<?php
// 初始化 WebSocket 服务器,在本地监听 8000 端口
$server = new Swoole\WebSocket\Server("localhost", 8000);
// 建立连接时触发
$server->on('open', function (Swoole\WebSocket\Server $server, $request) {
echo "server: handshake success with fd{$request->fd}\n";
});
// 收到消息时触发推送
$server->on('message', function (Swoole\WebSocket\Server $server, $frame) {
echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
$server->push($frame->fd, "this is server");
});
// 关闭 WebSocket 连接时触发
$server->on('close', function ($ser, $fd) {
echo "client {$fd} closed\n";
});
// 启动 WebSocket 服务器
$server->start();
编写完成后,将这段 PHP 代码保存到本地 websocket_server.php 文件。
WebSocket 客户端
在客户端,可以通过 JavaScript 调用浏览器内置的 WebSocket API 实现 WebSocket 客户端,实现代码和服务端差不多,无论服务端还是客户端 WebSocket 都是通过事件驱动的,我们在一个 HTML 文档中引入相应的 JavaScript 代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Chat Client</title>
</head>
<body>
<script>
window.onload = function () {
var nick = prompt("Enter your nickname");
var input = document.getElementById("input");
input.focus();
// 初始化客户端套接字并建立连接
var socket = new WebSocket("ws://localhost:8000");
// 连接建立时触发
socket.onopen = function (event) {
console.log("Connection open ...");
}
// 接收到服务端推送时执行
socket.onmessage = function (event) {
var msg = event.data;
var node = document.createTextNode(msg);
var div = document.createElement("div");
div.appendChild(node);
document.body.insertBefore(div, input);
input.scrollIntoView();
};
// 连接关闭时触发
socket.onclose = function (event) {
console.log("Connection closed ...");
}
input.onchange = function () {
var msg = nick + ": " + input.value;
// 将输入框变更信息通过 send 方法发送到服务器
socket.send(msg);
input.value = "";
};
}
</script>
<input id="input" style="width: 100%;">
</body>
</html>
将这个 HTML 文档命名为 websocket_client.html。
WebSocket 通信演示
接下来,我们在命令行启动 WebSocket 服务器:
php websocket.php
然后在浏览器中访问 websocket_client.html,首先会提示我们输入昵称:
输入之后点击确定,JavaScript 代码会继续往下执行,让输入框获取焦点,然后初始化 WebSocket 客户端并连接到服务器,这个时候通过开发者工具可以看到 Console 标签页已经输出了连接已建立日志:
在 Network 里面也可以看到 WebSocket 握手请求和响应:
这个时候我们在输入框中输入「你好,WebSocket!」并回车,即可触发客户端发送该数据到服务器,服务器接收到消息后会将其显示出来:
同时将「This is server」消息推送给客户端,客户端通过 onmessage 回调函数将获取到的数据显示出来。在开发者工具的 Network->WS 标签页可以查看 WebSocket 通信细节:
看起来,这个过程还是客户端触发服务器执行推送操作,但实际上,在建立连接并获取到这个客户端的唯一标识后,后续服务端资源有更新的情况下,仍然可以通过这个标识主动将更新推送给客户端,而不需要客户端发起拉取请求。WebSocket 服务器和客户端在实际项目中的实现可能会更加复杂,但是基本原理是一致的。
猜你喜欢
Swoole 实现长连接
阅读 2800Swoole 实现长连接,心跳
LaravelS基于Swoole实现高性能 HTTP 服务器
阅读 1982LaravelS基于Swoole 配置nginx等
Layui富文本视频等多功能
阅读 886Layui富文本多功能添加
Swoole 扩展安装与使用入门
阅读 2114Swoole从入门到实战
抖音接入
阅读 2255PHP 接入抖音开放平台
黑客、后门
阅读 1810留下的网站后门,可以作什么?
Resultful API规范
阅读 993什么是resultful
Laravel验证码
阅读 899Composer生成Laravel验证码