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

即可