Blogger Information
Blog 62
fans 7
comment 2
visits 58231
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
商桥系统的基本通讯原理
我是郭富城
Original
1153 people have browsed it

1. 客户端代码

1.1 控制器

  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Http\Request;
  4. // 仿百度商桥客户端
  5. class Bchat extends Controller
  6. {
  7. //百度商桥首页
  8. public function index() {
  9. return view('bchat/index');
  10. }
  11. }

1.2 客户端视图

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>仿百度商桥</title>
  6. <link rel="stylesheet" href="/static/plugins/layui/css/layui.css">
  7. <script src="/static/plugins/layui/layui.js"></script>
  8. </head>
  9. <body>
  10. <div>
  11. 这是测试内容啊老弟
  12. </div>
  13. </body>
  14. </html>
  15. <script>
  16. layui.use(['layer'], function() {
  17. var layer = layui.layer;
  18. $=layui.jquery;
  19. init_bchat();
  20. });
  21. // 百度商桥
  22. function init_bchat() {
  23. layer.open({
  24. type: 2,
  25. title: '百度商桥欢迎你',
  26. // shadeClose: true,
  27. shade: 0.2,
  28. area: ['80%', '80%'],
  29. content: '/bchat/index', //iframe的url
  30. btn: ['发送'],
  31. yes: function(index, layero) {
  32. var body = layer.getChildFrame('body', index);
  33. var iframeWin = window[layero.find('iframe')[0]['name']]; //得到iframe页的窗口对象,执行iframe页的方法:
  34. iframeWin.send();
  35. }
  36. });
  37. }
  38. </script>
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>客户端的聊天窗口</title>
  6. <link rel="stylesheet" href="/static/plugins/layui/css/layui.css">
  7. <script src="/static/plugins/layui/layui.js"></script>
  8. <link rel="stylesheet" href="/static/css/bchat.css">
  9. </head>
  10. <body>
  11. <!-- 消息内容展示 -->
  12. <div class="msg_show">
  13. </div>
  14. <hr class="layui-bg-black">
  15. <!-- 消息发送区 -->
  16. <div class="msg_send" contenteditable="true">请输入要发送的内容</div>
  17. </body>
  18. </html>
  19. <script>
  20. layui.use(['layer'], function() {
  21. var layer = layui.layer;
  22. $=layui.jquery;
  23. });
  24. // 假设服务端ip为127.0.0.1
  25. ws = new WebSocket("ws://127.0.0.1:2000");
  26. ws.onopen = function() {
  27. var data={};
  28. data.type= 'login';
  29. data.group = 'member';
  30. ws.send(JSON.stringify(data));
  31. // alert("连接成功");
  32. // ws.send('tom');
  33. // alert("给服务端发送一个字符串:tom");
  34. };
  35. ws.onmessage = function(e) {
  36. var data=JSON.parse(e.data);
  37. if (data.kefu_id > 0) {
  38. var html='<div class="msg_item">\
  39. <div class="nickname">客服'+ data.kefu_id +'说:</div>\
  40. <div class="contents">'+ data.msg +'</div>\
  41. </div>';
  42. $('.msg_show').append(html);
  43. } else {
  44. var html='<div class="msg_item msg_customer">\
  45. <div class="nickname">我说:</div>\
  46. <div class="contents">'+ data.msg +'</div>\
  47. </div>';
  48. $('.msg_show').append(html);
  49. }
  50. };
  51. // <!-- 发送消息 -->
  52. function send() {
  53. var data={};
  54. data.group = 'member';
  55. data.type='msg';//发送类型是message
  56. // data.touid=1;//发给哪个客服
  57. data.msg=$('.msg_send').html();
  58. ws.send(JSON.stringify(data));
  59. $('.msg_send').html('');
  60. }
  61. </script>

1.3 效果图

2. 客服端代码

2.1 客服端控制器

  1. <?php
  2. namespace App\Http\Controllers\admins;
  3. use App\Http\Controllers\Controller;
  4. use Illuminate\Http\Request;
  5. //后台客服
  6. class Kefu extends Controller
  7. {
  8. //
  9. public function index() {
  10. return view('admins/kefu/index');
  11. }
  12. }

2.2 客服端视图

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>后台客服</title>
  6. <link rel="stylesheet" href="/static/plugins/layui/css/layui.css">
  7. <script src="/static/plugins/layui/layui.js"></script>
  8. <link rel="stylesheet" href="/static/css/bchat.css">
  9. </head>
  10. <body>
  11. <div class="kefu">
  12. <div class="kefu_title">客户接待中心</div>
  13. <div class="kefu_detail">
  14. <!-- 左侧客户列表区 -->
  15. <div class="member_list">
  16. </div>
  17. <!-- 右侧客户对话区 -->
  18. <div class="message_list">
  19. <!-- 当前的聊天内容 -->
  20. <div class="message_content">
  21. </div>
  22. <!-- 消息发送区域 -->
  23. <div class="message_send" contenteditable="true">
  24. </div>
  25. <div class="btn_send"><button class="layui-btn" onclick="sendmsg()">发送</button></div>
  26. </div>
  27. </div>
  28. </div>
  29. </body>
  30. </html>
  31. <script>
  32. var user_list=[];//新用户列表
  33. layui.use(['layer'], function() {
  34. var layer = layui.layer;
  35. $=layui.jquery;
  36. });
  37. // 假设服务端ip为127.0.0.1
  38. ws = new WebSocket("ws://127.0.0.1:2000");
  39. ws.onopen = function() {
  40. var data={};
  41. data.type= 'login';
  42. data.group = 'admin';
  43. ws.send(JSON.stringify(data));
  44. // alert("连接成功");
  45. // ws.send('tom');
  46. // alert("给服务端发送一个字符串:tom");
  47. };
  48. ws.onmessage = function(e) {
  49. // console.log(e.data);
  50. var data = JSON.parse(e.data);
  51. //新客户来了
  52. if (data.type==='login') {
  53. if ($.inArray(data.customer_id,user_list)===-1) {
  54. user_list.push(data.customer_id);
  55. }
  56. build_kefu_user_list();
  57. return;
  58. }
  59. // 客户连接断开
  60. if (data.type==='logout') {
  61. var index = $.inArray(data.connection_id,user_list);
  62. if (index > -1) {
  63. user_list.splice(index,1);
  64. }
  65. build_kefu_user_list();
  66. return;
  67. }
  68. var msg_member_list = $('#member_'+ data.customer_id);
  69. if (msg_member_list.length===0) {
  70. var html_container = '<div id="member_' + data.customer_id +'"></div>';
  71. $('.message_content').append(html_container);
  72. }
  73. var html='<div class="msg_item">\
  74. <div class="nickname">'+ data.customer_id +'说:</div>\
  75. <div class="contents">'+ data.msg +'</div>\
  76. </div>';
  77. $('#member_'+ data.customer_id).append(html);
  78. $('#member_'+ data.customer_id).show().siblings('div').hide();
  79. };
  80. //构建客服端的客户列表
  81. function build_kefu_user_list() {
  82. var html='';
  83. $.each(user_list,function(i,v){
  84. html+=('<div class="member_item" onclick="checkme(this)" member_id="'+v+'">客户:'+ v +'</div>');
  85. });
  86. $('.member_list').html(html);
  87. }
  88. // 和某个客户聊天
  89. function checkme(obj) {
  90. $(obj).addClass('active').siblings('div').removeClass('active');
  91. var member_id=$(obj).attr('member_id');
  92. $('#member_'+ member_id).show().siblings('div').hide();
  93. }
  94. // <!-- 发送消息 -->
  95. function sendmsg() {
  96. // 获取当前聊天的客户
  97. var touid =parseInt($('.member_list div[class*="active"]').attr('member_id'));
  98. if (isNaN(touid)) {
  99. return layer.alert('请先选择客户',{icon:2});
  100. }
  101. var data={};
  102. data.group = 'admin';
  103. data.type='msg';//发送类型是message
  104. data.touid=touid;//发给哪个客户
  105. data.msg=$('.message_send').html();
  106. ws.send(JSON.stringify(data));
  107. $('.message_send').html('');
  108. var html='<div class="msg_item msg_kefu">\
  109. <div class="nickname">我说:</div>\
  110. <div class="contents">'+ data.msg +'</div>\
  111. </div>';
  112. $('.message_content').append(html);
  113. }
  114. </script>

2.3 效果图

3. websocket

参考WebSocket即时通讯原理实战https://www.php.cn/blog/detail/22780.html
下载PHP socket即时通讯框架。
https://www.workerman.net/download/workermanzip

  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. // 当收到客户端发来的数据后返回hello $data给客户端
  9. $ws_worker->onMessage = function($connection, $data)
  10. {
  11. // 向客户端发送hello $data
  12. // $connection->send($data);
  13. // 给所有人发消息
  14. // global $ws_worker;
  15. // foreach($ws_worker->connections as $conn)
  16. // {
  17. // // $conn->send("user[{$connection->uid}] said: $data");
  18. // $conn->send($data);
  19. // }
  20. // 服务器端收到客户端的信息后返回数据给客户端
  21. var_dump($connection->id);
  22. // return;
  23. global $ws_worker;
  24. $data = json_decode($data,true);
  25. // print_r($data);
  26. // 客户端有人登录进来了
  27. if ($data['type']==='login'){
  28. // 赋值
  29. $connection->group = $data['group'];
  30. //客户登录的时候
  31. if ($data['group']==='member') {
  32. //随机分配一个客服姐姐给他
  33. $admin_list=[];
  34. foreach($ws_worker->connections as $conn) {
  35. if ($conn->group==='admin') {
  36. $admin_list[]=$conn->id;
  37. }
  38. }
  39. // 分配一个随机客服
  40. $myadmin_index = array_rand($admin_list,1);//键名
  41. $connection->touid=$admin_list[$myadmin_index];
  42. // 通知客服有新用户进来
  43. foreach($ws_worker->connections as $conn)
  44. {
  45. if ($conn->id === $connection->touid) {
  46. $data['customer_id'] = $connection->id;
  47. $conn->send(json_encode($data));
  48. }
  49. }
  50. }
  51. }
  52. // 有新的消息过来了
  53. if ($data['type']==='msg'){
  54. // 赋值
  55. // 客服(管理)登录进来,发消息给用户
  56. if ($connection->group === 'admin'){
  57. $touid = $data['touid'];
  58. $msg = $data['msg'];
  59. foreach($ws_worker->connections as $conn)
  60. {
  61. //向对应的用户发送消息
  62. if($touid === $conn->id) {
  63. $msgData = [];
  64. $msgData['type'] = 'msg';
  65. $msgData['kefu_id'] = $connection->id;
  66. $msgData['msg'] = $msg;
  67. $conn->send(json_encode($msgData));
  68. // 把数据储存到数据库
  69. $data = ['from_id'=>$connection->id,'to_uid'=>$touid,'msg'=>$msg];
  70. $url = 'http://laravel.edu/kefumsg/save_msg';
  71. curl_post($url,$data);
  72. // var_dump($res);
  73. }
  74. // $conn->send("user[{$connection->uid}] said: $data");
  75. }
  76. }
  77. // 客户端登录进来
  78. if ($connection->group === 'member'){
  79. // $touid=$data['touid'];
  80. foreach($ws_worker->connections as $conn)
  81. {
  82. //向对应的用户发送消息
  83. if($connection->touid === $conn->id) {
  84. $data['customer_id'] = $connection->id;
  85. $conn->send(json_encode($data));
  86. // 储存数据
  87. $data = ['from_id'=>$connection->id,'to_uid'=>$connection->touid,'msg'=>$data['msg']];
  88. $url = 'http://laravel.edu/kefumsg/save_msg';
  89. curl_post($url,$data);
  90. }
  91. // $conn->send("user[{$connection->uid}] said: $data");
  92. }
  93. }
  94. }
  95. // 用户链接断开的时候
  96. $ws_worker->onClose = function($connection)
  97. {
  98. // 通知客服,有人掉线了
  99. global $ws_worker;
  100. foreach($ws_worker->connections as $conn) {
  101. if ($conn->group==='admin') {
  102. $data=[];
  103. $data['type']='logout';
  104. $data['connection_id']=$connection->id;
  105. $conn->send(json_encode($data));
  106. }
  107. }
  108. };
  109. };
  110. // 定义一个http请求函数
  111. // $url 是请求的链接
  112. // $postdata 是传输的数据,数组格式
  113. function curl_post( $url, $postdata ) {
  114. $header = array(
  115. 'Accept: application/json',
  116. );
  117. //初始化
  118. $curl = curl_init();
  119. //设置抓取的url
  120. curl_setopt($curl, CURLOPT_URL, $url);
  121. //设置头文件的信息作为数据流输出
  122. curl_setopt($curl, CURLOPT_HEADER, 0);
  123. //设置获取的信息以文件流的形式返回,而不是直接输出。
  124. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  125. // 超时设置
  126. curl_setopt($curl, CURLOPT_TIMEOUT, 10);
  127. // 超时设置,以毫秒为单位
  128. // curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
  129. // 设置请求头
  130. curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
  131. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE );
  132. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE );
  133. //设置post方式提交
  134. curl_setopt($curl, CURLOPT_POST, 1);
  135. curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata);
  136. //执行命令
  137. $data = curl_exec($curl);
  138. // 显示错误信息
  139. if (curl_error($curl)) {
  140. print "Error: " . curl_error($curl);
  141. } else {
  142. // 打印返回的内容
  143. curl_close($curl);
  144. return $data;
  145. }
  146. }
  147. // 运行worker
  148. Worker::runAll();

4. 效果演示

5. 总结

随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了。近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据。

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