5

一、Websocket基本概述

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信-允许服务器主动发信息给客户端

为什么需要WebSocket?
缺陷:HTTP的通信只能由客户端发起

WebSocket的特点:

  • 建立在TCP协议之上
  • 性能开销小通信高效
  • 客户端可以与任意服务器通信
  • 协议标识符ws wss
  • 持久化网络通信协议

二、代码实现

websocket服务端

ws_server.php

<?php

//创建websocket服务器对象,监听0.0.0.0:80端口
$ws = new swoole_websocket_server("0.0.0.0", 80);

//监听WebSocket连接打开事件
$ws->on('open', function ($ws, $request) {
    var_dump($request->fd, $request->get, $request->server);
    $ws->push($request->fd, "hello, welcome\n");
});

//监听WebSocket消息事件
$ws->on('message', function ($ws, $frame) {
    echo "Message: {$frame->data}\n";
    $ws->push($frame->fd, "server: {$frame->data}");
});

//监听WebSocket连接关闭事件
$ws->on('close', function ($ws, $fd) {
    echo "client-{$fd} is closed\n";
});

$ws->start();

因为我们是在docker 容器中,所以,我们使用 80 端口,这样可以在宿主机通过之前做的端口映射,就可以在宿主机浏览器访问该服务。

宿主机容器映射的端口查看:

➜  ~ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                                        NAMES
5ee6bfcc1310        7698f               "/bin/bash"         46 hours ago        Up 30 hours         0.0.0.0:2221->22/tcp, 0.0.0.0:8880->80/tcp   confident_jones

客户端静态页面

静态页面路径:/work/study/code/swoole/demo/static

ws_client.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket TEST</title>
</head>
<body>
<h1>Swoole-TEST</h1>
<script>
    var wsUrl = "ws://0.0.0.0:8880";
    var websocket = new WebSocket(wsUrl);

    // 实例化onopen对象
    websocket.onopen = function(evt){
        console.log("connected-swoole-success")
         websocket.send("Hello-Lily"); // 发送信息给服务端
    }

    // 实例化 onmessage
    websocket.onmessage = function(evt){
        console.log("ws-server-return-data"+evt.data)
    }

    // 实例化 onclose
    websocket.onclose = function(evt){
        console.log("close")
    }

    // onerror
    websocket.onerror = function (evt) {
        console.log("error:" + evt.data)
    }


</script>

</body>
</html>

宿主机浏览器访问:

clipboard.png

三、WebSocket服务优化

我们可以看到,上边的 ws_server.php 代码是面向过程代码,不够优雅,这里我们可以把这些方法封装起来,用面向对象的思路来优化。

ws.php

<?php

/**
 * WS 优化基础类库
 */

class Ws
{
    public $ws = null;

    CONST HOST = "0.0.0.0";
    CONST PORT = 80;

    public function __construct()
    {
        $this->ws = new swoole_websocket_server(static::HOST, static::PORT);

        $this->ws->on("open", [$this, "onOpen"]);
        $this->ws->on("message", [$this, "onMessage"]);
        $this->ws->on("close", [$this, "onClose"]);

        $this->ws->start();
    }

    /**
     * 监听ws连接事件
     * @param $ws
     * @param $request
     */
    public function onOpen($ws, $request)
    {
        var_dump($request->fd);
    }

    /**
     * 监听ws连接消息
     * @param $ws
     * @param $frame
     */
    public function onMessage($ws, $frame)
    {
        echo "ser-push-message:{$frame->data}\n";

        $ws->push($frame->fd, "server-push:".date("Y-m-d H:i:s"));

    }

    /**
     * 监听WebSocket连接关闭事件
     *
     * @param $ws
     * @param $fd
     */
    public function onClose($ws, $fd)
    {
        echo "clientid:{$fd} closed \n";
    }
}

$ws_obj = new Ws();

通过面向对象封装,上边的代码优雅了很多哈~


Corwien
6.3k 声望1.6k 粉丝

为者常成,行者常至。