user表
字段名称 | 类型 | 注释 |
---|---|---|
id | int | 自增id |
username | varchar | 名字 |
password | varchar | 密码 |
register.html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>注册title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
head>
<body>
<div style="width:600px;height:500px;margin: 30px auto;border:1px solid rgb(51, 23, 13);">
<h1 style="text-align: center">注册h1>
<form action="register.php" method="POST">
<div class="form-group">
<label for="exampleInputEmail1">用户名label>
<input type="username" name="username" class="form-control" id="exampleInputEmail1" placeholder="username">
div>
<div class="form-group">
<label for="exampleInputPassword1">密码label>
<input type="password" name="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
div>
<button type="submit" class="btn btn-primary" style="margin: 30px 270px;">注册button>
form>
div>
body>
html>
register.php
$pdo = new \PDO('mysql:host=127.0.0.1;dbname=chat', '用户名', '密码');
$pdo->exec('SET NAMES utf8'); //编码格式
//接收值
$username = $_POST['username'];
$password = md5($_POST['password']);
//插入
$sql = "insert into user(username,password) values('$username','$password')";
$c = $pdo->exec($sql);
// 判断是否成功
if($c){
echo "";
exit;
}
演示:
示例代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>聊天室title>
<link rel="stylesheet" type="text/css" href="css/chat.css" />
<style>
span {
color: #999;
margin-left: 10px;
}
style>
head>
<body class="keBody">
<div id="app">
<div class="kePublic">
<div class="content">
<div class="chatBox">
<div class="chatLeft">
<div class="chat01">
<div class="chat01_title">
<ul class="talkTo">
<li>
<a href="javascript:;">{{ messageList.username }}a>
<a @click="logout" href="javascript:;">退出a>
li>
ul>
<a class="close_btn" href="javascript:;">a>
div>
<div class="chat01_content" style="padding: 10px;" id="chat01_content">
<dl v-for="(v,k) in messageList" :key="k">
<dt><strong>{{v.username}}strong> 在 <time>{{ v.datetime }}time> 说:dt>
<dd>{{ v.content }}dd>
dl>
div>
div>
<div class="chat02">
<div class="chat02_title">
<label class="chat02_title_t">
<a target="_blank">聊天记录a>
label>
<div class="wl_faces_box">
<div class="wl_faces_content">
<div class="title">
<ul>
<li class="title_name">常用表情li>
<li class="wl_faces_close">
<span> span>
li>
ul>
div>
<div class="wl_faces_main">
<ul>
<li>
<a href="javascript:;">
<img src="img/emo_01.gif" />
a>
li>
<li>
<a href="javascript:;">
<img src="img/emo_02.gif" />
a>
li>
<li>
<a href="javascript:;">
<img src="img/emo_03.gif" />
a>
li>
ul>
div>
div>
<div class="wlf_icon">
div>
div>
div>
<div class="chat02_content">
<textarea id="textarea" v-model="content" placeholder="请输入内容按enter键快速发消息">textarea>
div>
<div class="chat02_bar">
<ul>
<li style="left: 20px; top: 10px; padding-left: 30px;">
apppws创建li>
<li style="right: 5px; top: 5px;">
<img @click="send" src="img/send_btn.jpg" id="send_btn">
li>
ul>
div>
div>
div>
<div class="chatRight">
<div class="chat03">
<div class="chat03_title">
<label class="chat03_title_t">成员列表label>
div>
<div class="chat03_content">
<select v-model="to">
<option value="">发给所有用户option>
<option :value="k" v-for="(v,k) in userList">{{v}}option>
select>
div>
div>
div>
<div style="clear: both;">
div>
div>
div>
<div :class="{'login':true,'hide':layerHide}">
<h1>登录h1>
<div><input v-model="username" type="text" placeholder="输入用户名">div>
<div><input v-model="password" type="password" placeholder="输入密码">div>
<div><input @click="dologin" type="button" value="登录">div>
div>
<div :class="{'layer':true,'hide':layerHide}">div>
div>
div>
body>
html>
<script src="./axios.min.js">script>
<script src="./vue.min.js">script>
<script>
new Vue({
el: '#app',
data: {
messageList: [], //消息列表
userList: [], // 在线用户列表
message: '', // 消息框中的内容
ws: null, // websocket 对象
layerHide: false, // 是否隐藏登录框
host: '127.0.0.1:8484', // 服务器地址
username: '', // 当前用户名
password: '',
to: '',
content: ''
},
methods: {
// 登录
dologin: function () {
axios.post('http://localhost:9999/login.php', {
username: this.username,
password: this.password
}).then(function (res) {
console.log(res.data);
if (res.data.code == 200) {
localStorage.setItem('jwt_token', res.data.jwt)
this.layerHide = true; // 隐藏登陆框
location.href = "index.html"
}
else {
alert(res.data.error)
}
})
},
// 退出
logout: function () {
// 断开连接
this.ws.close()
localStorage.removeItem('jwt_token')
location.href = "index.html"
},
// 发送消息
send: function () {
// 判断消息是发给谁的
if (this.to == '') {
// 群发:
this.ws.send('all:' + this.content);
} else {
// 发给某个人
this.ws.send(this.to + ':' + this.content);
}
this.content = ''
},
open: function () {
alert('连接成功');
},
// 收到消息时调用
ws_message: function (e) {
// 解析JSON
let data = JSON.parse(e.data)
// 根据消息的类型发处理消息
if (data.type == 'users'){
this.userList = data.users
}
else{
this.message=data.ws_message
}
this.messageList.push(data)
},
},
// 页面初始化
created: function () {
var token = localStorage.getItem('jwt_token')
if (token == undefined)
alert('请登录');
else {
this.layerHide = true; // 隐藏登陆框
// 连接聊天服务器
this.ws = new WebSocket('ws://127.0.0.1:8484?token=' + token)
this.ws.onopen = this.open
this.ws.onmessage = this.ws_message
this.ws.onerror = this.error
}
},
})
script>
显示:
登录服务的代码:
login.php
// 引入自动加载的 扩展包
require('./vendor/autoload.php');
// 生成令牌
use \Firebase\JWT\JWT;
// 连接数据库
$pdo = new \PDO('mysql:host=127.0.0.1;dbname=chat', 'root', '');
$pdo->exec('SET NAMES utf8');
// 接收原始数据
$post = file_get_contents('php://input');
// 把JSON转成数组
$_POST = json_decode($post, TRUE);
// 查询数据库
$stmt = $pdo->prepare("select * from user where username=? and password=?");
$stmt->execute([
$_POST['username'],
md5($_POST['password'])
]);
// 取出来所有信息
$user = $stmt->fetch(PDO::FETCH_ASSOC);
// var_dump($user);exit;
if($user)
{
$key = 'abcd1234';
$now = time();
$data = [
'id' => $user['id'],
'name' => $user['username'],
];
// var_dump($data);exit;
// 为这个数据生成令牌
$jwt = JWT::encode($data, $key);
// 返回 JSON 数据
echo json_encode([
'code'=>'200',
'jwt'=>$jwt,
]);
}
else
{
// 返回 JSON 数据
echo json_encode([
'code'=>'403',
'error'=>'用户名或者密码错误!',
]);
}
*里面包含lwt令牌
下载:composer require firebase/php-jwt
*vue.js
的下载
查看及安装:https://cn.vuejs.org/
*axios.js
的使用
安装及下载:https://www.kancloud.cn/yunye/axios/234845
start.php
use Workerman\Worker;
use Firebase\JWT\JWT;
// 引入workerman 自动加载
require_once __DIR__ . '/Workerman-master/Autoloader.php';
require('./vendor/autoload.php');
//保存所有用户
$allUsers = [];
// 客户端用户数据
$userConn = [];
// 有连接时调用
function connect($connection)
{
$connection->onWebSocketConnect = function ($connection, $http_header) {
global $allUsers, $userConn, $worker;
// 解析jwt令牌
try {
$key = 'abcd1234';
$data = JWT::decode($_GET['token'], $key, array('HS256'));
// 把id和name保存到这个连接上
$connection->uid = $data->id;
$connection->uname = $data->name;
// 保存当前连接到所有用户的数组中
$allUsers[$data->id] = $data->name;
$userConn[$data->id] = $connection;
// 如果用户连接成功 就通知所有其他客户端有新的客户端连接
foreach ($worker->connections as $v) {
$v->send(json_encode([
'username' => $data->name,
'content' => '加入了聊天室',
'datetime' => date('Y-m-d H:i'),
'type' => 'users',
'users' => $allUsers
]));
}
} catch (\Firebase\JWT\ExpiredException $e) {
// 关闭连接
$connection->close();
} catch (\Exception $e) {
// 关闭连接
$connection->close();
}
};
}
// 当收到数据时调用
function message($connection, $data)
{
// var_dump($data);
global $worker, $allUsers;
// 从消息中解析出第一个 :前面的内容 判断是单发还是群发
// 将字符串转为数组
$ret = explode(':', $data);
// 取出第一个元素 并去掉:前面的内容
$code = $ret[0];
unset($ret[0]);
// 再把数组拼成字符串
$rawData = implode(':', $ret);
// 判断第一个元素
if ($code == "all") {
// 群发
foreach ($worker->connections as $v) {
$v->send(json_encode([
'username' => $connection->uname,
'content' => $rawData,
'datetime' => date('Y-m-d H:i'),
'type' => 'users',
'users' => $allUsers
]));
}
} else {
// 引进保存客户端与对应用户id的数组
global $userConn;
$userConn[$code]->send(json_encode([
'username' => $connection->uname,
'datetime' => date('Y-m-d H:i'),
'type' => 'message',
'content' => $rawData,
'message' => $rawData
]));
}
}
// 当有客户端断开连接时调用
function close($connection, $data)
{
global $allUsers, $worker;
// 从用户列表数组中删除当前退出的用户
unset($allUsers[$connection->id]);
// 给所有用户发消息
foreach ($worker->connections as $v) {
$v->send(json_encode([
'username' => $data->name,
'content' => '退出了聊天室',
'datetime' => date('Y-m-d H:i'),
'type' => 'users',
'users' => $allUsers
]));
}
}
//创建一个workerman 的监听端口号
$worker = new Worker('websocket://0.0.0.0:8484');
//进程
$worker->count = 1;
// 设置回调函数
$worker->onConnect = 'connect';
$worker->onMessage = 'message';
$worker->onClose = 'close';
// 运行
$worker->runAll();
*启动:php start.php start
最终结果: 可以互相通信
源码:https://github.com/apppws/chatroom
*温馨提示:有什么问题或者有好的建议请发评论。