WorkerMan学习篇:websocket+workerman聊天功能设计(一):简单认证

版权声明:只要点赞,这篇文章就是你的。 https://blog.csdn.net/weixin_36691991/article/details/88929069

初步设计如下

1、websocket客户端连接服务端 是无脑的(这很重要) 
2、服务端需要记录连接进来的所有客户端(方便日后统一广播消息) 
3、服务端肯定能获得客户端ip。为此我们还需要客户端加入用户昵称来区分 
4、服务端可以无脑的向客户端发送消息。但是客户端怎么区分? 
于是我们自己定义一个格式来完成。 
4.1、普通消息我们用msg:xxx。如果开头是msg:那么后面的内容统统认定为普通消息 
4.2、认证消息notice:xxx,比如服务端认可客户端连接上了,则发送notice:开头的消息 
4.3、客户端发送login:昵称,代表连接服务端,并进行认证。

构建websocket客户端界

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="txtcontent" style="width: 500px;height: 250px;border: 1px solid gray"></div>
<div>所有用户:<select id="listuers"></select></div>
<div>你的昵称:<input type="text" id="username" /></div>
<div>
回复内容:
<textarea style="width: 500px;height: 100px" id="txtmsg"></textarea>
</div>
<div>
<button onclick="connectServer()">连接服务器</button>
<button onclick="send()">发送消息</button>
</div>
</body>
</html>



这里写图片描述

websocket客户端创建websocket连接,发送消息到服务端的代码

<script>
//创建一个socket实例
var socket = null; //初始为null
var isLogin = false; //是否登录到服务器上

//定义一个连服务的函数
function connectServer(){

var username = document.getElementById('username').value;
if (username == ''){
alert('用户昵称必填');
}

socket = new WebSocket("ws://39.106.30.83:2345");
socket.onopen = function() {
socket.send('login:' + username);
};
socket.onmessage = function(e) {
var getMsg = e.data;
if(/^notice:success$/.test(getMsg)){ //服务器验证通过
isLogin = true;
}else if(/^msg:/.test(getMsg)){ //代表是普通消息
var p = document.createElement('p');
p.innerHTML = '<span>收到消息:</span>' + getMsg.replace('msg:','');
document.getElementById('txtcontent').appendChild(p);
}
};

socket.onclose = function(){
isLogin = false;
}
}

//发送消息
function send(){
if (!isLogin){
alert('请先通过服务器验证');
}

var msg = document.getElementById('txtmsg').value;
//console.log(msg);

socket.send('msg:' + msg); //发送消息到服务端

//显示我们的消息到div中
var p = document.createElement('p');
p.innerHTML = '<span>回复消息:</span>' + msg;
document.getElementById('txtcontent').appendChild(p);
}

</script>



服务端代码:

<?php
use Workerman\Worker;
require_once __DIR__ . '/Workerman/Autoloader.php';
$clients = []; //保存客户端信息


// 创建一个Worker监听9090端口,使用websocket协议通讯
$ws_worker = new Worker('websocket://0.0.0.0:2345');

// 启动4个进程对外提供服务
$ws_worker->count = 4;

// 当收到客户端发来的数据后
$ws_worker->onMessage = function($connection, $data)
{
//这里用global的原因是:php是有作用域的,我们是在onMessage这个回调还是里操作外面的数组
//想要改变作用域外面的数组,就global一下
global $clients;

//验证客户端用户名在3-20个字符
if(preg_match('/^login:(\w{1,20})/i',$data,$result)){ //代表是客户端认证

$ip = $connection->getRemoteIp();
if(!array_key_exists($ip,$clients)){ //必须是之前没有注册过

$clients[$ip] = $result[1]; //把新用户保存起来

// 向客户端发送数据
$connection->send('notice:success'); //验证成功消息
$connection->send('msg:welcome '.$result[1]); //普通消息
echo $ip .':' .$result[1] .'login' . PHP_EOL; //这是为了演示,控制台打印信息
}

}elseif(preg_match('/^msg:(.*?)/isU',$data,$msgset)){ //代表是客户端发送的普通消息

if(array_key_exists($connection->getRemoteIp(),$clients)){ //必须是之前验证通过的客户端
echo 'get msg:' . $msgset[1] .PHP_EOL; //这是为了演示,控制台打印信息
if($msgset[1] == 'nihao'){
//如果收到'nihao',就给客户端发送'nihao 用户名'
//给客户端发送普通消息
$connection->send('msg:nihao '.$clients[$connection->getRemoteIp()]);
}
}
}

// 设置连接的onClose回调
$connection->onClose = function($connection) //客户端主动关闭
{
global $clients;
unset($clients[$connection->getRemoteIp()]);

echo "connection closed\n";
};
};

// 运行worker
Worker::runAll();




这里写图片描述

服务器控制台打印: 
这里写图片描述

猜你喜欢

转载自blog.csdn.net/weixin_36691991/article/details/88929069