✅【WebSocket与Hyperf项目实战】实现在线聊天室

✅【WebSocket与Hyperf项目实战】实现在线聊天室

有一天☝️,你想跟你的网络soulmate通过网络交流,聊到某种程度,不想用市面上已经有的社交软件去聊天了(可能聊天内容比较私密比较不好公开,或者说比较想要一些独特的专属于你们自己的功能)。

于是🤙,自制了一个专属于websocket的聊天工具……

✅【WebSocket与Hyperf项目实战】实现在线聊天室

客户端vue3

服务器:hyperf

🔻初识Hyperf

hyperf 是 一个php协程框架,Hyperf这个名字的来源(Hyper取自Hyperspeed[超高速], f取自Flexibility[灵活性],可见作者取名字的设计理念。)

提问:hyperf特别的点在哪呢?比其他框架特别且突出的点在哪呢?

:协程。

提问:什么是协程?

  • 协程是一种轻量级的线程,由用户代码来调度和管理,而不是由操作系统内核来进行调度
  • 举个例子🌰:请求A创建了协程A请求B创建了协程B,那么在处理协程A的时候代码跑到了查询MySQL的语句上,这个时候协程A则会触发协程切换,协程A就继续等待I/O设备返回结果,那么此时就会切换到协程B,开始处理协程B的逻辑,当又遇到了一个I/O操作便又触发协程切换,再回过来从协程A刚才切走的地方继续执行,如此反复,遇到I/O操作就切换到另一个协程去继续执行而非一直阻塞等待。

🔻服务端 websocket

创建项目

composer create-project hyperf/hyperf-skeleton

✅【WebSocket与Hyperf项目实战】实现在线聊天室

启动项目:

cd hyperf-skeleton
php bin/hyperf.php start // 启动

安装

composer require hyperf/websocket-server

配置 Server

修改 config/autoload/server.php

<?php
return [
    'servers'=> [
        'name' => 'ws',
        'type' => Server::SERVER_WEBSOCKET,
        'host' => '0.0.0.0',
        'port' => 9502,
        'sock_type' => SWOOLE_SOCK_TCP,
        'callbacks' => [
            Event::ON_HAND_SHAKE => [Hyperf\WebSocketServer\Server::class, 'onHandShake'],
            Event::ON_MESSAGE => [Hyperf\WebSocketServer\Server::class, 'onMessage'],
            Event::ON_CLOSE => [Hyperf\WebSocketServer\Server::class, 'onClose'],
        ],
    ],
];

配置路由

配置config/routes.php 加个 ws的路由配置,代码如下:

Router::addServer('ws', function () {
    Router::get('/', 'App\Controller\WebSocketController');
});

创建对应控制器

app/Controller下,创建一个控制器WebSocketController.php

✅【WebSocket与Hyperf项目实战】实现在线聊天室

WebSocketController.php

<?php
declare(strict_types=1);

namespace App\Controller;

// 引用一些类和接口
use Hyperf\Contract\OnCloseInterface;
use Hyperf\Contract\OnMessageInterface;
use Hyperf\Contract\OnOpenInterface;
use Hyperf\Engine\WebSocket\Frame;
use Hyperf\Engine\WebSocket\Response;
use Hyperf\WebSocketServer\Constant\Opcode;
use Swoole\Server;
use Swoole\WebSocket\Server as WebSocketServer;

// WebSocketController类
class WebSocketController implements OnMessageInterface, OnOpenInterface, OnCloseInterface
{
  // 处理接收到消息的时间 - 一般接收客户端发送过来的消息
  public function onMessage($server, $frame): void
  {
    $response = (new Response($server, $frame))->init($frame);
    if($frame->opcode == Opcode::PING) {
      $response->push(new Frame(opcode: Opcode::PONG));
      return;
    }
    $response->push(new Frame(payloadData: '您好,client'));
  }

  // websocket 连接关闭
  public function onClose($server, int $fd, int $reactorId):void
  {
    var_dump('closed');
  }
   
  // websocket 连接打开,这个可以发送欢迎语那些逻辑
  public function onOpen($server, $request): void
  {
    $response = (new Response($server))->init($request);
    $response->push(new Frame(payloadData: 'Opened'));
  }
}

加完这些代码之后,重新启动一下项目:php bin/hyperf.php start

🔻客户端 websocket

连接

客户端websocket

✅【WebSocket与Hyperf项目实战】实现在线聊天室

聊天室

✅【WebSocket与Hyperf项目实战】实现在线聊天室

简单用vue3搭建一个聊天室应用程序。

每个用户注册登录都有一个chatId

账户信息

// 通过手机号去注册

{
    phone: '12138121388', // 通过手机号注册
    nickname: '巴拉巴拉', // 昵称
    avatar: '', // 通过上传到云库上
    // xxx 其余一些个人信息
}

入到个人信息表,从而每个人获得一个唯一的chatId(md5)

chatId phone nickname avatar
1 12138121388 古力娜扎 gulinaza.png
2 12138121389 迪丽热巴 dilireba.png

建立连接

vue3项目新建一个socket文件

let Socket // WebSocket对象
let setIntervalWebSocketPush // 定时心跳💓

// 创建WebSocket并建立与服务端连接
export function createSocket() {
    if (Socket) return
    
    const WSS_URL = `ws://127.0.0.1:9502`
    Socket = new WebSocket(WSS_URL)
    
    Socket.onopen = onopenWS
    Socket.onmessage = onmessageWS
    Socket.onerror = onerrorWS
    Socket.onclose = oncloseWS
}

/↓心跳💓/

export function sendPing() {
  Socket.send('ping')
  setIntervalWebSocketPush = setInterval(() => {
    Socket.send('ping')
  }, 5000) // 每隔5秒钟执行一次
}

/↓打开后发送心跳/

export function onopenWS() {
  console.log('服务器连接成功')
  sendPing() // 发送心跳
}

/↓数据接收/

export function onmessageWS(e) {
  window.dispatchEvent(new CustomEvent('onmessageWS', {
    detail: {
      data: e
    }
  }))
}

/↓连接失败重连/

export function onerrorWS() {
  clearInterval(setIntervalWebSocketPush)
  Socket.close()
  createSocket() // 重连
}

/↓关闭连接/

export function oncloseWS() {
  clearInterval(setIntervalWebSocketPush)
  console.log('与服务器连接断开')
}

这段代码呢主要处理了创建WebSocket与服务器进行连接消息接收失败时心跳重连这块。

🔻微信安全通信协议

微信安全通信协议mmtls

☎️ 希望对大家有所帮助,如有错误,望不吝赐教,欢迎评论区留言互相学习。感谢阅读,祝您开发有乐趣。

原文链接:https://juejin.cn/post/7350302578184421387 作者:盏灯

(0)
上一篇 2024年3月27日 下午4:54
下一篇 2024年3月27日 下午5:04

相关推荐

发表回复

登录后才能评论