WebSocket是一个持久化的协议,举个简单的例子,http1.0的生命周期是以request作为界定的,也就是一个request,一个response,对于http来说,本次client与server的会话到此结束;而在http1.1中,稍微有所改进,即添加了keep-alive,也就是在一个http连接中可以进行多个request请求和多个response接受操作。然而在实时通信中,并没有多大的作用,http只能由client发起请求,server才能返回信息,即server不能主动向client推送信息,无法满足实时通信的要求。而WebSocket可以进行持久化连接,即client只需进行一次握手,成功后即可持续进行数据通信,值得关注的是WebSocket实现client与server之间全双工通信,即server端有数据更新时可以主动推送给client端。
演示地址 http://dev.topsts.cn/websocket.html
客户端实现(HTML5 JS)
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>WebSocket Test</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<script type="text/javascript" src="http://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript">
(function(){
if ("WebSocket" in window) {
console.log("您的浏览器支持 WebSocket!");
// 打开一个 web socket
var ws = new WebSocket("ws://dev.topsts.cn:9502");
console.log('连接状态:',ws);
// 打开连接
ws.onopen = function() {('#messages').append('WebSocket 连接成功 <br>');
};
// 接收到消息
ws.onmessage = function(evt) {
var received_msg = evt.data;
console.log('一个消息:',evt);
('#messages').append(evt.data+'<br>');
};
// 出现错误
ws.onerror = function(err) {
console.warn('出现错误:',err);
alert("出现错误");
}
// 关闭 websocket
ws.onclose = function() {
console.log("连接已关闭...");
alert("连接已关闭...");
};
} else {
// 浏览器不支持 WebSocket
alert("您的浏览器不支持 WebSocket!");
}
// 发送消息('#send').click(function() {
var content = window.prompt('请输入内容', '默认内容');
ws.send(content);
});
// 关闭连接
$('#close').click(function() {
ws.close();
console.log("连接主动关闭");
});
});
</script>
</head>
<body>
<div id="main">
<p>本页面用于测试WebSocket,使用ws://dev.topsts.cn:9502</p>
<button id="send">发送数据</button>
<button id="close">关闭连接</button>
<p><br></p>
<div id="messages">稍等,正在连接ws://dev.topsts.cn:9502<br></div>
</div>
</body>
</html>
服务端实现 Swoole PHP
<?php
class WebsocketTest
{
public server;
publicfds = []; // 存放fd的数组
public function __construct()
{
this->server = new swoole_websocket_server("0.0.0.0", 9502);this->server->set([
// 'daemonize' => 1, // 设置后台运行
]);
// 打开链接
this->server->on('open', function (swoole_websocket_serverserver, request) {
echo "server: handshake success with fd{request->fd}\n";
// 收集链接用户
this->fds[] =request->fd;
this->fds = array_unique(this->fds); // 去重
this->server->push(request->fd, '系统:您的UID为' . request->fd);
foreach (this->fds as value) {server->push(value, '广播:UID' .request->fd . '用户已经上线');
}
});
// 接收数据
this->server->on('message', function (swoole_websocket_serverserver, frame) {
echo "receive from {frame->fd}:{frame->data},opcode:{frame->opcode},fin:{frame->finish}\n";
foreach (this->fds as value) {this->server->push(value, '发送:(UID' .frame->fd . ')' . frame->data);
}
});
// 关闭链接this->server->on('close', function (ser,fd) {
echo "client {fd} closed\n";
// 找到并删除元素
array_splice(this->fds, array_search(fd,this->fds), 1);
foreach (this->fds asvalue) {
this->server->push(value, '系统:UID' . fd . '已经下线');
}
});
// 当做HTTP服务使用this->server->on('request', function (request,response) {
// 接收http请求从get获取message参数的值,给用户推送
// this->server->connections 遍历所有websocket连接用户的fd,给所有用户推送
foreach (this->server->connections as fd) {this->server->push(fd,request->get['message']);
}
});
$this->server->start();
}
}
new WebsocketTest();
启动
php index.php
即可