为什么要使用WebSocket?
- HTTP不能主动的向客户端发送数据,HTTP进行的通信只能是由客户端主动发起
- WebSocket可以主动向客户发送消息.进行消息推送等等
- WebSocket开销小,通信高效
- 客户端可以与任意服务端连接
- 持久化网络通信协议,可以理解为一个长连接,可以做通信,聊天室等等
WebSocket服务端
<?php
$server = new swoole_websocket_server("0.0.0.0", 8812);
$server->on('open', 'onOpen');
$server->on('message','onMessage');
$server->on('close', 'onClose');
/**
* 监听连接打开事件
* @param $server
* @param $request
*/
function onOpen ($server , $request){
print_r($request);
}
/**
* 监听接收消息事件
* @param $server
* @param $frame
*/
function onMessage ($server, $frame){
print_r($frame);
$server->push($frame->fd,date("Y-m-d H:i:s",time())." data: ".$frame->data." finish:".$frame->finish." fd: ".$frame->fd." opcode: ".$frame->opcode);
}
function onClose($server, $fd ,$reactorId){
}
$server->start();
官方文档 https://wiki.swoole.com/wiki/page/397.html
swoole_websocket_server
继承自swoole_http_server
WebSocket有三个额外的回调函数:
-
onMessage
回调函数必选function onMessage(swoole_websocket_server $server, swoole_websocket_frame $frame)
swoole_websocket_frame
有四个属性:$frame->fd
,客户端的socket id
,使用$server->push
推送数据时需要用到$frame->data
,数据内容,可以是文本内容也可以是二进制数据,可以通过opcode的值来判断$frame->opcode
,WebSocket的OpCode类型,可以参考WebSocket协议标准文档$frame->finish
, 表示数据帧是否完整,一个WebSocket请求可能会分成多个数据帧进行发送(底层已经实现了自动合并数据帧,现在不用担心接收到的数据帧不完整)
-
onOpen
和onHandShake
回调函数可选的
在WebSocket中,使用push
函数来发送数据给客户端
function swoole_websocket_server->push(int $fd, $data, int $opcode = 1, bool $finish = true);
参数:
$fd
发送数据的客户端连接id$data
发送的数据
返回数据是 true 或者 false
在WebSocket中,也可以跟之前的HTTP服务中一样.使用浏览器来访问静态页面
$server->set([
'enable_static_handler' => true,
'document_root' => '/marun/'
]);
WebSocket客户端
在这里,使用js来构建一个WebSocket
客户端
参考文档 :
http://www.ruanyifeng.com/blog/2017/05/websocket.html
https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ws_client</title>
</head>
<body>
<h1>WebSocket_client</h1>
<script>
var url = "ws://127.0.0.1:8812";
//实例对象的onopen属性
var websocket = new WebSocket(url);
/**
* 监听WebSocket连接
* @param ev
*/
websocket.onopen = function (ev) {
console.log("conected-swoole-success");
//给服务端发送消息
websocket.send('hello world');
};
/**
* 监听接收消息事件
* @param ev
*/
websocket.onmessage = function (ev) {
console.log("ws-server-return-data: " + ev.data);
};
/**
* 监听连接关闭事件
* @param ev
*/
websocket.onclose =function (ev) {
console.log('ws-server-closed')
};
/**
* 监听错误信息
* @param ev
* @param e
*/
websocket.onerror = function (ev,e) {
console.log("error: " +ev.data);
};
</script>
</body>
</html>
我们这里可以通过浏览器来访问这个WebSocket客户端页面