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 相关文章推荐
Bo-Blog专用的给Windows服务器的IIS Rewrite程序
Aug 26 PHP
phplock(php进程锁) v1.0 beta1
Nov 24 PHP
详解php的魔术方法__get()和__set()使用介绍
Sep 19 PHP
排序算法之PHP版快速排序、冒泡排序
Apr 09 PHP
使用php批量删除数据库下所有前缀为prefix_的表
Jun 09 PHP
ThinkPHP CURD方法之field方法详解
Jun 18 PHP
PHP实现通过Luhn算法校验信用卡卡号是否有效
Mar 23 PHP
针对多用户实现头像上传功能PHP代码 适用于登陆页面制作
Aug 17 PHP
php中strtotime函数性能分析
Nov 20 PHP
php 使用curl模拟ip和来源进行访问的实现方法
May 02 PHP
PHP使用xpath解析XML的方法详解
May 20 PHP
PHP PDOStatement::setAttribute讲解
Feb 01 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
在PHP中使用与Perl兼容的正则表达式
2006/11/26 PHP
基于empty函数的判断详解
2013/06/17 PHP
PHP文件读写操作相关函数总结
2014/11/18 PHP
php在apache环境下实现gzip配置方法
2015/04/02 PHP
通过PHP自带的服务器来查看正则匹配结果的方法
2015/12/24 PHP
Yii2结合Workerman的websocket示例详解
2018/09/10 PHP
PHP实现的策略模式示例
2019/03/20 PHP
javascript:void(0)的真正含义实例分析
2008/08/20 Javascript
浅析JavaScript原型继承的陷阱
2013/12/03 Javascript
js生成缩略图后上传并利用canvas重绘
2014/05/15 Javascript
JavaScript使用pop方法移除数组最后一个元素用法实例
2015/04/06 Javascript
Grunt入门教程(自动任务运行器)
2015/08/06 Javascript
javascript编程异常处理实例小结
2015/11/30 Javascript
你所未知的3种Node.js代码优化方式
2016/02/25 Javascript
Jquery删除css属性的简单方法
2016/12/04 Javascript
canvas快速绘制圆形、三角形、矩形、多边形方法介绍
2016/12/29 Javascript
jQuery实现的鼠标滚轮控制图片缩放功能实例
2017/10/14 jQuery
利用nginx + node在阿里云部署https的步骤详解
2017/12/19 Javascript
JavaScript中发出HTTP请求最常用的方法
2018/07/12 Javascript
jQuery实现左右两个列表框的内容相互移动功能示例
2019/01/27 jQuery
JS如何监听div的resize事件详解
2020/12/03 Javascript
图文详解WinPE下安装Python
2016/05/17 Python
python中import reload __import__的区别详解
2017/10/16 Python
Python爬虫常用库的安装及其环境配置
2018/09/19 Python
python构建基础的爬虫教学
2018/12/23 Python
Python 安装第三方库 pip install 安装慢安装不上的解决办法
2019/06/18 Python
python点击鼠标获取坐标(Graphics)
2019/08/10 Python
详解css3 mask遮罩实现一些特效
2018/10/24 HTML / CSS
详解CSS3 Media Queries中媒体属性的使用
2016/02/29 HTML / CSS
日本高岛屋百货购物网站:TAKASHIMAYA
2019/03/24 全球购物
学生旷课检讨书500字
2014/10/28 职场文书
社区元宵节活动总结
2015/02/06 职场文书
企业投资意向书
2015/05/09 职场文书
律师函格式范本
2015/05/27 职场文书
Nginx+Tomcat实现负载均衡、动静分离的原理解析
2021/03/31 Servers
pytorch 实现多个Dataloader同时训练
2021/05/29 Python