有一天☝️,你想跟你的网络soulmate通过网络交流,聊到某种程度,不想用市面上已经有的社交软件去聊天了(可能聊天内容比较私密比较不好公开,或者说比较想要一些独特的专属于你们自己的功能)。
于是🤙,自制了一个专属于websocket的聊天工具......
客户端 :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
创建项目
bash
composer create-project hyperf/hyperf-skeleton
启动项目:
bash
cd hyperf-skeleton
php bin/hyperf.php start // 启动
安装
bash
composer require hyperf/websocket-server
配置 Server
修改 config/autoload/server.php
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
的路由配置,代码如下:
php
Router::addServer('ws', function () {
Router::get('/', 'App\Controller\WebSocketController');
});
创建对应控制器
在app/Controller
下,创建一个控制器WebSocketController.php
WebSocketController.php
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
聊天室
简单用vue3搭建一个聊天室应用程序。
每个用户注册登录都有一个chatId
账户信息
// 通过手机号去注册
csharp
{
phone: '12138121388', // 通过手机号注册
nickname: '巴拉巴拉', // 昵称
avatar: '', // 通过上传到云库上
// xxx 其余一些个人信息
}
入到个人信息表,从而每个人获得一个唯一的chatId(md5)
chatId | phone | nickname | avatar |
---|---|---|---|
1 | 12138121388 | 古力娜扎 | gulinaza.png |
2 | 12138121389 | 迪丽热巴 | dilireba.png |
建立连接
vue3项目
新建一个socket
文件
js
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
}
/↓心跳💓/
js
export function sendPing() {
Socket.send('ping')
setIntervalWebSocketPush = setInterval(() => {
Socket.send('ping')
}, 5000) // 每隔5秒钟执行一次
}
/↓打开后发送心跳/
js
export function onopenWS() {
console.log('服务器连接成功')
sendPing() // 发送心跳
}
/↓数据接收/
js
export function onmessageWS(e) {
window.dispatchEvent(new CustomEvent('onmessageWS', {
detail: {
data: e
}
}))
}
/↓连接失败重连/
js
export function onerrorWS() {
clearInterval(setIntervalWebSocketPush)
Socket.close()
createSocket() // 重连
}
/↓关闭连接/
js
export function oncloseWS() {
clearInterval(setIntervalWebSocketPush)
console.log('与服务器连接断开')
}
这段代码呢主要处理了创建WebSocket与服务器进行连接
、消息接收
、失败时心跳重连
这块。
🔻微信安全通信协议
微信安全通信协议mmtls
☎️ 希望对大家有所帮助,如有错误,望不吝赐教,欢迎评论区留言互相学习。感谢阅读,祝您开发有乐趣。