Blogger Information
Blog 57
fans 3
comment 0
visits 60507
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
仿百度商桥项目-使用workerman进行websocket通信/模拟商桥群发消息
岂几岂几
Original
1789 people have browsed it

使用workerman进行websocket通信/模拟商桥群发消息

学习心得

  • 提供 websocket 通信服务的服务器, 像一个跟所有人保持通信的传声筒, 它可以接收来自客户端的消息, 也能主动给客户端发送消息. 而 http 通信, 服务器只能跟发送请求的客户端交互, 不能主动发送消息给客户端.

1. 使用workerman进行websocket通信

1.1. workerman的下载和简单开发实例说明

  1. 访问workerman官网,点击“下载”栏目,在“workerman内核(Linux Windows通用)”框中点击“下载ZIP压缩文件”开始下载workerman文件包,并解压缩(假设解压缩到Workerman目录中):
  2. 参考workerman说明文档中“简单开发实例”的实例二,创建wk_test.php文件,并拷贝实例二ws_test.php文件中的代码到创建的文件中:
  3. 在wk_test.php文件所在目录,用git batch启动workerman服务端:
  4. 打开chrome浏览器,按F12打开调试控制台,在Console一栏输入客户端给服务端发送消息的代码:

1.2. 实例中的细节说明

  • websocket 链接跟 http 链接的区别: http 链接在客户端向服务器发送请求, 服务器返回响应后, 链接就会断开; websocket 链接在链接成功后, 可以持续通信, 链接会一直保持.

  • workerman 应用在服务器中的位置跟 Apache , Nginx 相同. 即, web 服务器.

  • 使用 workerman 创建使用 websocket 通信的应用服务器的一般步骤:

    1. 创建一个 Worder 应用对象, 传入参数指定应用负责处理 websocket 通信. $ws_worker = new Worker("websocket://0.0.0.0:2000"); ; 其中的 0.0.0.0:2000 表示接受任意IP客户端发送到服务器 2000 端口的链接请求.
    2. 启动提供 websocket 通信的系统进程数. $ws_worker->count = 4; ;
    3. 指定收到客户端发送来数据后的处理数据的方法脚本: $ws_worker->onMessage = function($connection, $data) {...} ; 其中参数 $connection 是发送数据的客户端与服务器的 websocket 链接; $data 是客户端发送过来的数据.
    4. 指定当客户端断开链接时的处理脚本. $ws_worker->onClose = function($connection) {...} ; 其中参数 $connection 是即将关闭的 websocket 链接.
    5. 启动 Worker 应用.
    6. 服务端使用 websocket 链接的 send(消息字符串) 向该链接的客户端发送消息数据. $connection->send('hello!');
    7. Worder 对象的 connections 属性是当前与服务器保持通讯的 websocket 链接数组.
  • 客户端与提供 websocket 通信的服务器交互的一般步骤:

    1. 创建一个跟服务器进行 websocket 通信的链接: ws = new WebSocket("ws://127.0.0.1:2000"); . 其中 127.0.0.1 是客户端要与之创建 websocket 链接的服务器地址, 2000 是服务器监听链接和数据收发的端口号.
    2. 指定当连接创建成功时的回调处理方法, 一般链接创建成功后, 就发送唯一标识当前客户端信息的数据, 如保存在 cookie 中的 用户id 等. ws.onopen = function() {// 一般发送客户端的唯一标识给服务器存储 }
    3. 指定收到服务器返回的消息时的处理方法脚本. ws.onmessage = function(e) {// 收到服务器的消息了, 处理消息数据吧}
    4. 客户端同样使用 websocket 连接的 send(消息字符串) 方法向服务器发送数据.

2. 模拟商桥群发消息

  • 实现思路: 服务器类内置一个connections属性数组, connections 属性保存有所有成功跟客户端创建链接的连接对象. 当某个客户端给服务器发送消息时, 服务器遍历 connections 中链接对象, 给连接对象的客户端发送消息, 即可实现群发.

代码

  • 1- 服务端
  1. <?php
  2. use Workerman\Worker;
  3. require_once __DIR__ . '/workerman/Autoloader.php';
  4. // 注意:这里与上个例子不同,使用的是websocket协议
  5. $ws_worker = new Worker("websocket://0.0.0.0:2000");
  6. // 启动4个进程对外提供服务
  7. $ws_worker->count = 4;
  8. // 当接收到客户端发来的消息时的处理方法
  9. $ws_worker->onMessage = function($connection, $data)
  10. {
  11. // 发送消息的连接id
  12. $message['from_id'] = $connection->id;
  13. // 消息内容
  14. $message['msg'] = $data
  15. // 转成json字符串
  16. $jsonStr = json_encode($message);
  17. // 遍历当前所有的链接对象, 给连接对象对应的客户端发送数据
  18. foreach($ws_worker->connection as $conn) {
  19. $connection->send($jsonStr);
  20. }
  21. }
  22. // 运行worker
  23. Worker::runAll();
  • 2- 客户端
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>"百度商桥"客户端</title>
  7. <link rel="stylesheet" href="/static/plugin/layui/css/layui.css" media="all">
  8. <script src="/static/plugin/layui/layui.js"></script>
  9. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
  10. <style>
  11. * {
  12. margin: 0;
  13. padding: 0;
  14. box-sizing: border-box;
  15. }
  16. body {
  17. background-color: #fafafa;
  18. }
  19. .im {
  20. width: 400px;
  21. height: 520px;
  22. background-color: wheat;
  23. margin: 40px auto;
  24. padding: 10px;
  25. }
  26. .im .history {
  27. background-color: white;
  28. border: 1px solid #aaa;
  29. width: 100%;
  30. height: 290px;
  31. padding: 5px;
  32. overflow-y: auto;
  33. }
  34. .im .inputing {
  35. background-color: white;
  36. border: 1px solid #aaa;
  37. width: 100%;
  38. height: 150px;
  39. margin-top: 10px;
  40. padding: 5px;
  41. outline: none;
  42. }
  43. .im .btn-area {
  44. width: 100%;
  45. text-align: right;
  46. margin-top: 10px;
  47. }
  48. .msg-box-friend {
  49. padding: 10px;
  50. width: 75%;
  51. margin: 5px auto 0 5px;
  52. background-color: lightblue;
  53. border: 1px solid #ccc;
  54. border-radius: 5px;
  55. /* overflow-x: wordwrap; */
  56. white-space:normal;
  57. }
  58. .msg-box-me {
  59. padding: 10px;
  60. width: 75%;
  61. margin: 5px 5px 0 auto;
  62. background-color: wheat;
  63. border: 1px solid #ccc;
  64. border-radius: 5px;
  65. /* overflow-x: wordwrap; */
  66. white-space:normal;
  67. }
  68. </style>
  69. </head>
  70. <body>
  71. <div class="im">
  72. <div class="history">
  73. </div>
  74. <!-- contenteditable="true", 这个div就可编辑了 -->
  75. <div class="inputing" contenteditable="true">
  76. </div>
  77. <div class="btn-area">
  78. <span class="layui-btn layui-btn-success" onclick="send()">发送</span>
  79. </div>
  80. </div>
  81. </body>
  82. <script>
  83. layui.use(['layer'], function() {
  84. layer = layui.layer;
  85. });
  86. // 假设服务端ip为127.0.0.1
  87. ws = new WebSocket("ws://127.0.0.1:2000");
  88. /* 当客户端连通服务器端的时候 */
  89. ws.onopen = function() {
  90. // ...
  91. };
  92. ws.onmessage = function(e) {
  93. // alert("收到服务端的消息:" + e.data);
  94. var receive = JSON.parse(e.data);
  95. var str = "<div class='msg-box-friend'>"+receive.from_id+"说: "+receive.msg+"</div>";
  96. $(str).appendTo('.history');
  97. };
  98. function send() {
  99. // 消息框
  100. var str = "<div class='msg-box-me'>我说: "+$('.inputing').html()+"</div>";
  101. var data = {};
  102. // 标识此次发送的数据是发送消息
  103. data.type='msg';
  104. // 标识是从客服端发的
  105. data.group = 'admin'
  106. // 标识私聊的对象id,0标识群发. DEL_客户连接时由系统随机分配客服小姐姐, 不需要手动指定了
  107. // data.sendId = 0;
  108. // 要发送的消息
  109. data.msg = $('.inputing').html();
  110. // 在消息历史中显示发送的消息
  111. $(str).appendTo('.history');
  112. // 发送JSON格式的数据
  113. ws.send(JSON.stringify(data));
  114. $('.inputing').html('');
  115. }
  116. </script>
  117. </html>
Correcting teacher:GuanhuiGuanhui

Correction status:qualified

Teacher's comments:可以!尽量贴出效果图!
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post