swoole实现WebSocket服务器基础案例

环境准备

虚拟机

  • VirtualBox

服务端

  • OS:CentOS 7
  • IP:192.168.55.171
  • PHP:PHP 7.3.0(已安装swoole 4.4.0扩展)
  • 域名:sy.net

客户端

  • OS:Windows 10
  • IP:192.168.55.1
  • hosts:192.168.55.171 sy.net

swoole 4.4.0下载:http://swoole-1252906962.cos.ap-shanghai.myqcloud.com/linuxglibc/4.4.0/swoole_4.4.0_163f39b9_x86-64.tar.xz

参数说明

服务端

  • new swoole_websocket_server()
  • swoole_websocket_server继承自swoole_http_server
  • on/start函数
  • open/message/close
  • push()发送数据

服务端脚本

/wwwroot/sy.net/socket/ws_server.php

<?php
//创建WebSocket服务器对象,监听0.0.0.0:9502端口
$ws = new swoole_websocket_server('0.0.0.0', 9502);//客户端链接成功
//$ws = new swoole_websocket_server("192.168.55.171", 9502);//客户端链接成功
//$ws = new swoole_websocket_server("127.0.0.1", 9502);//客户端链接失败


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

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

//监听WebSocket连接关闭事件
$ws->on('close', function ($ws, $fd) {
    echo "client-{$fd} is closed\n";
    //删除已断开的客户端
    unset($ws->user_c[$fd-1]);
});
$ws->start();

启动服务
/application/php/bin/php /wwwroot/sy.net/socket/ws_server.php

启动服务,后台运行,且屏幕不输出
/application/php/bin/php /wwwroot/sy.net/socket/ws_server.php > /dev/null &

查看服务是否启动

[root@sy-pc ~]# netstat -lntup|grep 9502
tcp        0      0 0.0.0.0:9502            0.0.0.0:*               LISTEN      6859/php 

客户端脚本

/wwwroot/sy.net/socket/ws_client.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="msg"></div>
<input type="text" id="text">
<button type="button" onclick="sendMessage()">发送数据</button>
<button type="button" onclick="closeConnect()">断开链接</button>
<button type="button" onclick="againConnect()">手动重连</button>
</body>
<script>
    var msg = document.getElementById("msg");
    //var wsServer = 'ws://192.168.55.171:9502';
    var wsServer = 'ws://sy.net:9502';//如果客户端配置了hosts文件,则可以使用域名
    var websocket = null;

    function firstConnect() {
        websocket = new WebSocket(wsServer);
        websocket.onopen = function (evt) {
            //websocket.readyState 属性:
            /*
            CONNECTING  0   The connection is not yet open.
            OPEN    1   The connection is open and ready to communicate.
            CLOSING 2   The connection is in the process of closing.
            CLOSED  3   The connection is closed or couldn't be opened.
            */
            msg.innerHTML = websocket.readyState;
            console.log("Connected to WebSocket server.");
        };

        websocket.onclose = function (evt) {
            msg.innerHTML += 'Disconnected<br>';
            console.log("Disconnected");
        };

        websocket.onmessage = function (evt) {
            msg.innerHTML += evt.data + '<br>';
            console.log('Retrieved data from server: ' + evt.data);
        };

        websocket.onerror = function (evt, e) {
            console.log('Error occured: ' + evt.data);
        };
    }
    firstConnect();

    function sendMessage() {
        ipttext = document.getElementById('text')
        var text = ipttext.value;
        ipttext.value = '';
        if (websocket.readyState != 1) {
            msg.innerHTML += 'WebSocket is closed.<br>';
            return false;
        }
        websocket.send(text);
    }

    function closeConnect() {
        websocket.close();
    }

    //WebSocket断开重连
    function againConnect() {
        if (websocket.readyState != 1) {
            firstConnect();
        }
    }
    //setInterval(againConnect, 5000);
</script>
</html>

运行效果

浏览器http://192.168.55.171:9501,得到
HTTP 400 Bad Request
Powered by Swoole

测试1:WebSocket链接

浏览器http://sy.net/socket/index.html?t=123

在这里插入图片描述
在这里插入图片描述

服务器端控制台输出

Swoole\Http\Request Object
(
    [fd] => 1
    [streamId] => 0
    [header] => Array
        (
            [host] => sy.net:9502
            [connection] => Upgrade
            [pragma] => no-cache
            [cache-control] => no-cache
            [user-agent] => Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36
            [upgrade] => websocket
            [origin] => http://sy.net
            [sec-websocket-version] => 13
            [accept-encoding] => gzip, deflate
            [accept-language] => zh-CN,zh;q=0.9,en;q=0.8
            [sec-websocket-key] => +Hyrt1z8IWYzyWLAkRI13g==
            [sec-websocket-extensions] => permessage-deflate; client_max_window_bits
        )

    [server] => Array
        (
            [request_method] => GET
            [request_uri] => /
            [path_info] => /
            [request_time] => 1565422354
            [request_time_float] => 1565422354.8778
            [server_protocol] => HTTP/1.1
            [server_port] => 9502
            [remote_port] => 15980
            [remote_addr] => 192.168.55.1
            [master_time] => 1565422354
        )

    [request] => 
    [cookie] => 
    [get] => 
    [files] => 
    [post] => 
    [tmpfiles] => 
)

测试2:客户端发送信息

客户端发送数据{"type":"eat","data":{}}
在这里插入图片描述
服务端控制台输出:

Swoole\WebSocket\Frame Object
(
    [fd] => 1
    [data] => {"type":"eat","data":{}}
    [opcode] => 1
    [finish] => 1
)

对应服务端代码print_r($frame);语句输出内容。

测试3:服务端停止服务

服务端停止socket服务,则客户端触发JS中的websocket.onclose = ......代码。
在这里插入图片描述

测试4:客户端断开WebSocket链接

客户端点击断开链接按钮,则服务端控制台显示:

client-1 is closed

服务端检测脚本

可以参考 shell监控PHP守护进程[DB|OL] https://blog.csdn.net/zhou16333/article/details/98531445 。

获得守护进程PID的shell语句:
ps -aux | grep ws_server.php | grep -v grep | head -1 | awk '{print $2}'
netstat -lntup | grep 9502 | awk '{print $7}' | awk -F / '{print $1}'

参考文献

[1] 官网[DB|OL]. https://wiki.swoole.com/wiki/page/479.html .
[2] 利用Swoole实现PHP+websocket 聊天室[DB|OL]. https://www.jianshu.com/p/fedbb9d2d999 .

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值