「IM系列」WebSocket实践教程:基础入门实战

之前七七八八也发过一下相关文章,但是比较乱,所以从本章节开始,进行系统性整理输出一下。——开源技术小栈

什么是 WebSocket

WebSocket是一种通信协议,可在单个TCP连接上进行全双工通信。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就可以建立持久性的连接,并进行双向数据传输。

典型握手通信

客户端请求

GET /chat HTTP/1.1
Host: wss.tinywan.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

服务器响应

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

客户端的简单示例

var ws = new WebSocket("wss://echo.websocket.org");

ws.onopen = function(evt
  console.log("Connection open ..."); 
  ws.send("Hello WebSockets!");
};

ws.onmessage = function(evt{
  console.log( "Received Message: " + evt.data);
  ws.close();
};

ws.onclose = function(evt{
  console.log("Connection closed.");
};     

实战

实战相关框架和插件组件统一使用超高性能可扩展PHP框架:webman 以及生态进行编写。

安装webman框架

如何安装使用请查阅文章 Webman:您的专属HTTP代理服务器,让网络浏览更加畅快!,这里不再详细阐述。

安装GatewayWorker插件

简介

GatewayWorker基于Workerman开发的一个项目框架,用于快速开发TCP长连接应用,例如app推送服务端、即时IM服务端、游戏服务端、物联网、智能家居等等

GatewayWorker使用经典的Gateway和Worker进程模型。Gateway进程负责维持客户端连接,并转发客户端的数据给BusinessWorker进程处理,BusinessWorker进程负责处理实际的业务逻辑(默认调用Events.php处理业务),并将结果推送给对应的客户端。Gateway服务和BusinessWorker服务可以分开部署在不同的服务器上,实现分布式集群。

GatewayWorker提供非常方便的API,可以全局广播数据、可以向某个群体广播数据、也可以向某个特定客户端推送数据。配合Workerman的定时器,也可以定时推送数据。

安装

D:dnmpwwwwebman-admin>composer require webman/gateway-worker

./composer.json has been updated
Running composer update webman/gateway-worker
Loading composer repositories with package information
Updating dependencies
Lock file operations: 2 installs, 0 updates, 0 removals
  - Locking webman/gateway-worker (v1.0.8)
  - Locking workerman/gateway-worker (v3.1.1)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 2 installs, 2 updates, 0 removals
  - Downloading tinywan/jwt (v1.8.2)
  - Downloading workerman/gateway-worker (v3.1.1)
  - Downloading webman/gateway-worker (v1.0.8)
  - Downloading workbunny/webman-nacos (1.1.7)
  - Upgrading tinywan/jwt (v1.8.1 => v1.8.2): Extracting archive
  - Installing workerman/gateway-worker (v3.1.1): Extracting archive
  - Installing webman/gateway-worker (v1.0.8): Extracting archive
  - Downgrading workbunny/webman-nacos (1.1.8 => 1.1.7): Extracting archive
> supportPlugin::install
> supportPlugin::install
Generating autoload files
29 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found
Using version ^1.0 for webman/gateway-worker

安装成功后配置文件目录路径

「IM系列」WebSocket实践教程:基础入门实战

业务文件路径

「IM系列」WebSocket实践教程:基础入门实战

跳转进程配置文件


use WebmanGatewayWorkerGateway;
use WebmanGatewayWorkerBusinessWorker;
use WebmanGatewayWorkerRegister;

return [
    'gateway' => [
        'handler'     => Gateway::class,
        'listen'      => 'websocket://0.0.0.0:8783',
        'count'       => cpu_count(),
        'reloadable'  => false,
        'constructor' => ['config' => [
            'lanIp'           => '127.0.0.1',
            'startPort'       => 2300,
            'pingInterval'    => 25,
            'pingData'        => '{"type":"ping"}',
            'registerAddress' => '127.0.0.1:12306',
            'onConnect'       => function(){},
        ]]
    ],
    'worker' => [
        'handler'     => BusinessWorker::class,
        'count'       => cpu_count()*2,
        'constructor' => ['config' => [
            'eventHandler'    => pluginwebmangatewayEvents::class,
            'name'            => 'ChatBusinessWorker',
            'registerAddress' => '127.0.0.1:12306',
        ]]
    ],
    'register' => [
        'handler'     => Register::class,
        'listen'      => 'text://127.0.0.1:12306',
        'count'       => 1// Must be 1
        'constructor' => []
    ],
];

注意:websocket端口8783。注册中心register端口12306

启动服务

「IM系列」WebSocket实践教程:基础入门实战

打开浏览器console进行测试

var ws = new WebSocket("ws://127.0.0.1:8387");

ws.onopen = function(evt
  console.log("Connection open ..."); 
  ws.send("Hello WebSockets!");
};

ws.onmessage = function(evt{
  console.log( "Received Message: " + evt.data);
  ws.close();
};

ws.onclose = function(evt{
  console.log("Connection closed.");
};  
「IM系列」WebSocket实践教程:基础入门实战

进阶

编写业务配置

修改pluginwebmangatewayEvents.php业务处理事件onMessage()方法

/**
 * @desc onMessage
 * @param string $clientId
 * @param string $message
 * @return false
 * @author Tinywan(ShaoBo Wan)
 */
public static function onMessage(string $clientId, string $message): bool
{
    $originMessage = json_decode($messagetrue);
    if (json_last_error() != JSON_ERROR_NONE) {
        Gateway::closeClient($clientId, json_encode([
            'code' => 500,
            'msg' => '无效的json数据'
        ], JSON_UNESCAPED_UNICODE));
        return false;
    }
    return Gateway::sendToClient($clientId, json_encode([
        'code' => 200,
        'msg' => '请求发送成功',
        'data' => $originMessage
    ], JSON_UNESCAPED_UNICODE));
}

无效数据

console 控制台

「IM系列」WebSocket实践教程:基础入门实战

网络发送和接受情况

「IM系列」WebSocket实践教程:基础入门实战

有效数据

var ws = new WebSocket("ws://127.0.0.1:8783");

ws.onopen = function(evt{
    console.log("Connection open ...");
    let $_content = {
        "mode"1,
        "from_username""Tinywan",
        "to_user_id""10000",
        "content""Hi, 开源技术小栈",
    };
    ws.send(JSON.stringify($_content));
};

ws.onmessage = function(evt{
    console.log( "Received Message: " + evt.data);
};

ws.onclose = function(evt{
    console.log("Connection closed.");
};

console 控制台

「IM系列」WebSocket实践教程:基础入门实战

网络发送和接受情况

「IM系列」WebSocket实践教程:基础入门实战

源码

文章相关源码地址:https://github.com/Tinywan/webman-admin


原文始发于微信公众号(开源技术小栈):「IM系列」WebSocket实践教程:基础入门实战

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/248007.html

(0)
李, 若俞的头像李, 若俞

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!