swoole和websocket简单聊天室开发


Posted in PHP onNovember 18, 2017

首先,我想说下写代码的一些习惯,第一,任何可配置的参数或变量都要写到一个config文件中。第二,代码中一定要有日志记录和完善的报错并记录报错。言归正传,swoole应该是每个phper必须要了解的,它号称重新定义了php。此聊天室利用了swoole高并发并且异步非阻塞的特点提高了程序的性能。

首先,定义一个 swoole_lock swoole_websocket_server ,并且配置参数,具体参数详情可以去swoole官网查看。

public function start()
{
  $this->lock = new swoole_lock(SWOOLE_MUTEX);

  // 对文件或数组进行锁操作,已达到同步
  $this->server = new swoole_websocket_server($this->addr, $this->port);

  // swoole提供的Websocket Server
  $this->server->set(array(
   'daemonize' => 0,
   'worker_num' => 4,
   'task_worker_num' => 10,
   'max_request' => 1000,
   'log_file' => ROOT_PATH . 'storage\\logs\\swoole.log'  

  // swoole日志路径,必须是绝对路径
  ));

  $this->server->on('open', array($this, 'onOpen'));
  $this->server->on('message', array($this, 'onMessage'));
  $this->server->on('task', array($this, 'onTask'));
  $this->server->on('finish', array($this, 'onFinish'));
  $this->server->on('close', array($this, 'onClose'));

 // 启动服务
  $this->server->start();
}

当有客户端链接时,简单记录客户端的信息。

public function onOpen($server, $request)
  {
   $message = array(
    'remote_addr' => $request->server['remote_addr'],
    'request_time' => date('Y-m-d H:i:s', $request->server['request_time'])
   );
   write_log($message);
  }

当有客户端发送信息时,对信息进行处理。

public function onMessage($server, $frame)
  {
   $data = json_decode($frame->data);

   switch ($data->type) {
    case 'init':
    case 'INIT':
     $this->users[$frame->fd] = $data->message;、

   // 记录每个链接的信息,同样不要尝试打印出来看,因为你只能看到自己的链接信息
     $message = '欢迎' . $data->message . '加入了聊天室';
     $response = array(
      'type' => 1, // 1代表系统消息,2代表用户聊天
      'message' => $message
     );
     break;
    case 'chat':
    case 'CHAT':
     $message = $data->message;
     $response = array(
      'type' => 2, // 1代表系统消息,2代表用户聊天
      'username' => $this->users[$frame->fd],
      'message' => $message
     );
     break;
    default:
     return false;
   }

 // 将信息交给task处理
   $this->server->task($response);
  }

  public function onTask($server, $task_id, $from_id, $message)
  {
 // 迭代所有的客户端链接,将消息推送过去。(如果你尝试将 $this->server->connections 打印出来,那么你会发现他是空的。但当时用 foreach 去循环时,它确实有用。)
   foreach ($this->server->connections as $fd) {
    $this->server->push($fd, json_encode($message));
   }
   $server->finish( 'Task' . $task_id . 'Finished' . PHP_EOL);
  }

最后,当客户端断开链接时,利用锁机制,同步删除客户端信息,并记录日志。

public function onClose($server, $fd)
  {
   $username = $this->users[$fd];
   // 释放客户端,利用锁进行同步
   $this->lock->lock();
   unset($this->users[$fd]);
   $this->lock->unlock();

   if( $username ) {
    $response = array(
     'type' => 1, // 1代表系统消息,2代表用户聊天
     'message' => $username . '离开了聊天室'
    );
    $this->server->task($response);
   }


   write_log( $fd . ' disconnected');
  }

服务端完了,下面就是客户端,很简单,只需要用websocket链接就ok!

// websocket
  let address = 'ws://<?php echo CLIENT_CONNECT_ADDR . ':' . CLIENT_CONNECT_PORT ?>';
  let webSocket = new WebSocket(address);
  webSocket.onerror = function (event) {
   alert('服务器连接错误,请稍后重试');
  };
  webSocket.onopen = function (event) {
   if(!sessionStorage.getItem('username')) {
    setName();
   }else {
    username = sessionStorage.getItem('username')
    webSocket.send(JSON.stringify({
     'message': username,
     'type': 'init'
    }));
   }
  };
  webSocket.onmessage = function (event) {
   console.log(event);
   let data = JSON.parse(event.data);
   if (data.type == 1) {
    $('#chat-list2').append('<li class="ui-border-tb"><span class="username">系统消息:</span><span class="message">' + data.message + '</span></li>');
   } else if (data.type == 2) {
    $('#chat-list2').append('<li class="ui-border-tb"><span class="username">' + data.username + ':</span><span class="message">' + data.message + '</span></li>');
   }

  };
  webSocket.onclose = function (event) {
   alert('散了吧,服务器都关了');
  };

详细代码可以去我的github下载

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
第八节 访问方式 [8]
Oct 09 PHP
手把手教你使用DedeCms V3的在线采集图文教程
Apr 03 PHP
php 遍历数据表数据并列表横向排列的代码
Sep 05 PHP
Could not load type System.ServiceModel.Activation.HttpModule解决办法
Dec 29 PHP
php中json_encode处理gbk与gb2312中文乱码问题的解决方法
Jul 10 PHP
php+mysql实现数据库随机重排实例
Oct 17 PHP
PHP的Laravel框架中使用AdminLTE模板来编写网站后台界面
Mar 21 PHP
thinkphp3.2.0 setInc方法 源码全面解析
Jan 29 PHP
php 读取文件夹下所有图片、文件的实例
Oct 17 PHP
基于laravel缓冲cache的用法详解
Oct 23 PHP
PHP简单实现图片格式转换(jpg转png,gif转png等)
Oct 30 PHP
PhpStorm 如何优雅的调试Hyperf的方法步骤
Nov 24 PHP
php单元测试phpunit入门实例教程
Nov 17 #PHP
PHP开发之归档格式phar文件概念与用法详解【创建,使用,解包还原提取】
Nov 17 #PHP
PHP流Streams、包装器wrapper概念与用法实例详解
Nov 17 #PHP
PHP实现求两个字符串最长公共子串的方法示例
Nov 17 #PHP
PHP实现求解最长公共子串问题的方法
Nov 17 #PHP
php大小写转换函数(strtolower、strtoupper)用法介绍
Nov 17 #PHP
PHP 实现人民币小写转换成大写的方法及大小写转换函数
Nov 17 #PHP
You might like
ThinkPHP5实现作业管理系统中处理学生未交作业与已交作业信息的方法
2016/11/12 PHP
javascript面向对象编程(一) 实例代码
2010/06/25 Javascript
JavaScript传递变量: 值传递?引用传递?
2011/02/22 Javascript
js中获取事件对象的方法小结
2011/03/13 Javascript
检测input每次的输入是否合法遇到汉字输入就有问题
2012/05/23 Javascript
jQuery中DOM操作实例分析
2015/01/23 Javascript
jQuery模拟原生态App上拉刷新下拉加载更多页面及原理
2015/08/10 Javascript
JS实现左右拖动改变内容显示区域大小的方法
2015/10/13 Javascript
Javascript编程之继承实例汇总
2015/11/28 Javascript
漫谈JS引擎的运行机制 你应该知道什么
2016/06/15 Javascript
js实现精确到毫秒的倒计时效果
2016/08/05 Javascript
Angular 2父子组件数据传递之@Input和@Output详解 (上)
2017/07/05 Javascript
vue+Vue Router多级侧导航切换路由(页面)的实现代码
2018/12/20 Javascript
jquery获取file表单选择文件的路径、名字、大小、类型
2019/01/18 jQuery
Vue指令v-for遍历输出JavaScript数组及json对象的常见方式小结
2019/02/11 Javascript
vue 使用element-ui中的Notification自定义按钮并实现关闭功能及如何处理多个通知
2019/08/17 Javascript
JavaScript setTimeout()基本用法有哪些
2020/11/04 Javascript
Python中使用第三方库xlrd来读取Excel示例
2015/04/05 Python
深入理解NumPy简明教程---数组1
2016/12/17 Python
python下载图片实现方法(超简单)
2017/07/21 Python
Python之批量创建文件的实例讲解
2018/05/10 Python
python opencv 读取本地视频文件 修改ffmpeg的方法
2019/01/26 Python
python日志通过不同的等级打印不同的颜色(示例代码)
2021/01/13 Python
html5+css3气泡组件的实现
2014/11/21 HTML / CSS
百思买美国官网:Best Buy
2016/07/28 全球购物
Pat McGrath Labs官网:世界上最有影响力的化妆师推出的彩妆品牌
2018/01/07 全球购物
指针和引用有什么区别
2013/01/13 面试题
Linux机考试题
2015/10/16 面试题
教师申诉制度
2014/01/29 职场文书
五一手机促销方案
2014/03/08 职场文书
信息技术课后反思
2014/04/27 职场文书
上课说话检讨书500字
2014/11/01 职场文书
营销计划书
2015/01/17 职场文书
污染环境建议书
2015/09/14 职场文书
公司岗位说明书
2015/10/08 职场文书
教你使用一行Python代码玩遍童年的小游戏
2021/08/23 Python