workerman搭建聊天室
首先,先打开官网手册 http://doc.workerman.net/
根据手册里安装里的提示,完成环境检测,和安装对应的扩展,并把对应的WorkerMan代码包下载解压至根目录
在根目录下创建一个index.php
index.php代码如下:
<?php
use Workerman\Worker;
require_once __DIR__ . '/Workerman/Autoloader.php';
use Workerman\Lib\Timer; Worker::$daemonize = true;
// 所有的打印输出全部保存在/stdout.log文件中
Worker::$stdoutFile = '/stdout.log'; // 注意:这里与上个例子不同,使用的是websocket协议
$ws_worker = new Worker("websocket://0.0.0.0:2999"); // 启动1个进程对外提供服务
$ws_worker->count = 1; // 设置实例的名称
$ws_worker->name = 'Worker1'; //定义全局变量
$user_ip = []; // 心跳间隔120秒
define('HEARTBEAT_TIME', 120); // 当收到客户端发来的数据后返回hello $data给客户端
//闭包使用use传递参数进行使用
$ws_worker->onMessage = function($connection, $data)use($ws_worker)
{
// 给connection临时设置一个lastMessageTime属性,用来记录上次收到消息的时间
$connection->lastMessageTime = time(); global $user_ip;
file_put_contents('666.txt',$data, FILE_APPEND | LOCK_EX); //用户发送的信息内容
$content = substr($data,mb_strpos($data,':') + 1,mb_strlen($data));
//用户发送信息的状态请求,比如,登录,发送消息等等
$sort = strstr($data,':',true);
//获取用户的ip
$ip = $connection->getRemoteIp();
if($sort == 'login'){
//判断用户昵称是否重复
$array_search = array_search($content,$user_ip, false);
if( $array_search != $ip && !empty($array_search)){
//触发回调,关闭服务器和客户端链接
$connection->close('sort:'.'401');
}
if(!array_key_exists($ip,$user_ip)){
//记录登录时间
echo '登录ip:'.$ip.' 登录时间:'.date('Y-m-d H:i:s', time()).'\n';
}
// 录入ip和昵称
$user_ip[$ip] = $content;
//登录成功,返回200
$connection->send('sort:'.'200'); }else if($sort == 'text'){
//获取用户发送的消息,并返回
// $connection->send('text:'.$user_ip[$ip].':'.$content); //广播,通过$ws_worker->connections获取所有连接服务端的对象,循环给所有在线用户推送信息
foreach($ws_worker->connections as $connection)
{
$connection->send('text:'.$user_ip[$ip].'发送消息:'.$content);
}
}else{
//未知错误,返回500
$connection->send('sort:'.'500');
} }; // 进程启动后设置一个每秒运行一次的定时器
$ws_worker->onWorkerStart = function($ws_worker) {
Timer::add(1, function()use($ws_worker){
$time_now = time();
foreach($ws_worker->connections as $connection) {
// 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间
if (empty($connection->lastMessageTime)) {
$connection->lastMessageTime = $time_now;
continue;
}
// 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接,返回402
if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
$connection->close('sort:'.'402');
}
}
});
}; //用户断开连接时触发函数
$ws_worker->onClose = function($connection)
{
global $user_ip;
//清除用户的ip和用户名
$ip = $connection->getRemoteIp();
unset($user_ip[$ip]);
echo 'ip:'. $ip . ' 下线时间:'.date('Y-m-d H:i:s', time()).'\n';
}; // 运行worker
Worker::runAll();
然后在根目录中的index.html写入以下代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://libs.baidu.com/jquery/1.8.3/jquery.min.js"></script>
</head>
<body>
<div>你的昵称:<input type="text" id="username" value=""/></div>
<div>
回复内容:
<textarea style="width: 500px;height: 100px" id="content" value=''></textarea>
</div>
<div>
<input type="button" onclick="login()" value="连接服务器">
<input type="button" onclick="send()" value="发送消息">
<input type="button" onclick="quit()" value="退出">
</div> <script> var socket = null; //将socket实例保存到变量中
var isLogin = false; //登录标识符 var ws; function login(){
var name = document.getElementById('username').value;
if(name.length == 0 || name == ''){
alert('请输入昵称');
return false;
}
ws = new WebSocket("ws://www.xxx.com:2999"); ws.onopen = function() {
ws.send('login:'+name);
ws.onmessage = function(e) {
console.log(e);
callback(e);
}
}
} function send(){
if(!isLogin){
alert('请先连接服务器');
return false;
} var content =document.getElementById('content').value; ws.send('text:' + content);
ws.onmessage = function(e) {
callback(e);
}
} function quit(){
if(!isLogin){
alert('请先连接服务器');
}
ws.send('quit');
ws.onmessage = function(e){
callback(e);
}
} //返回值处理
function callback(e){
//返回的状态
var sort = e.data.substring(0,e.data.indexOf(':'));
//返回的内容
var content = e.data.substring(e.data.indexOf(':')+1); if(sort == 'text'){
alert(content);
}else if(sort == 'sort'){ if(content == 401){
alert('用户名重复,连接失败');
}else if(content == 200){
isLogin = true;
alert('连接成功');
}else if(content == 402){
isLogin = false;
alert('长时间未发消息,已断开连接,请重新连接服务器');
}else if(content == 202){
isLogin = false;
alert('成功断开连接');
}else if(content == 500){
alert('未知错误');
}else{
alert('未知错误');
} }else{
alert('连接失败');
}
}
</script>
</body>
</html>
弄好了之后,打开终端,cd 至网站根目录,执行index.php脚本,监听端口,并加入守护进程
php index.php start -d
执行成功,那么你的一个简单的即时通讯功能就完成了
测试:两个不同的用户登录网页,输入昵称,连接服务器,其中一个发送消息,另一个在页面中有收到
那么恭喜你,一个简单的即时通讯功能就这样做出来了
参考文章:https://blog.csdn.net/qq_33862644/article/details/79554321
workerman搭建聊天室的更多相关文章
- 使用nodejs+express+socketio+mysql搭建聊天室
使用nodejs+express+socketio+mysql搭建聊天室 nodejs相关的资料已经很多了,我也是学习中吧,于是把socket的教程看了下,学着做了个聊天室,然后加入简单的操作mysq ...
- 使用Angular和Nodejs搭建聊天室
一,利用Node搭建静态服务器 这个是这个项目的底层支撑部分.用来支持静态资源文件像html, css, gif, jpg, png, javascript, json, plain text等等静态 ...
- laravel整合workerman做聊天室
测试工具 http://www.blue-zero.com/WebSocket/ 2018年8月6日17:28:24 <?php namespace App\Console\Commands; ...
- 使用socket.io搭建聊天室
最近在学习nodejs,需要找一些项目练练手.找来找去发现了一个聊天室的教程,足够简单,也能从中学到一些东西.下面记录我练习过程中待一些笔记. nodeJS模块 共用到了2个模块,express和so ...
- SpringBoot--使用socket搭建聊天室
1.添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- Workerman创建聊天室实例
// 标记是全局启动 define('GLOBAL_START', 1); require_once __DIR__ . '/Workerman/Connection.php'; require_on ...
- 基于swoole搭建聊天室程序
1. 创建websocket服务器 swoole从1.7.9版本开始, 内置了websocket服务器功能,我们只需几行简单的PHP代码,就可以创建出一个异步非阻塞多进程的WebSocket服务器. ...
- 使用 NIO 搭建一个聊天室
使用 NIO 搭建一个聊天室 前面刚讲了使用 Socket 搭建了一个 Http Server,在最后我们使用了 NIO 对 Server 进行了优化,然后有小伙伴问到怎么使用 Socket 搭建聊天 ...
- 使用WebRTC搭建前端视频聊天室——点对点通信篇
WebRTC给我们带来了浏览器中的视频.音频聊天体验.但个人认为,它最实用的特性莫过于DataChannel——在浏览器之间建立一个点对点的数据通道.在DataChannel之前,浏览器到浏览器的数据 ...
随机推荐
- 第二十五章 ansible基础
一.Ansible概述 1.什么是Ansible Ansible是一个自动化统一配置管理工具,自动化主要体现在Ansible集成了丰富模块以及功能组件,可以通过一个命令完成一系列的操作,进而能减少重复 ...
- C# 面试前的准备_基础知识点的回顾_03
1.HTTP中Post和Get区别 这忒简单了吧,大家是不是感觉到兴奋了,长舒一口气了,终于出现了一个可以聊上10分钟的问题了. 根据HTTP规范,Get用于信息获取,而且应该是安全的和幂等的. 参数 ...
- 【多次实践】win10+ubuntu18.04lts双系统安装葵花宝典(安装篇)
这个教程诞生的缘由很简单,吃的太饱,硬是要折腾,结果,这一折腾便是20余小时,故写此文,帮助后来者少走弯路! 在本文开始,请先允许我对网上很多类似的教程嗤之以鼻,很成功地让我走了很多的弯路,一些有效简 ...
- Anderson《空气动力学基础》5th读书笔记 第3记——流动类型
一.连续介质与自由分子流动 分子之间相互碰撞的平均距离定义为平均自由程 .如果平均自由程的数量级远小于飞行器的尺寸时,此时,分子对物体的碰撞如此频繁以至于物体无法分辨出单个的分子碰撞,这时,对物体 ...
- Vue实例中封装api接口的思路 在页面中用async,await调用方法请求
一般我们写小型的项目是用不到封装axios实例 但是当我们写大型项目时 接口有时候多到有上百个接口,那我们在请求一次调用一次接口,接口上好多都是重复的,这个时候我们就可以封装axios实例,既节省了 ...
- Redis【一】 RESP协议
https://redis.io/topics/protocol RESP:redis序列化协议 client-server交流 二进制安全的 网络层 client端建立tcp连接到Server po ...
- python接口自动化测试遇到的问题及解决方案
工作中xml中的某一个字段是全网唯一,这就需要进行参数化处理.此次对这一个字段进行参数化处理引用了random模块和index()函数.代码如下: #!/usr/bin/python # -*- co ...
- Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)
Linux 网络编程的5种IO模型:多路复用(select/poll/epoll) 背景 我们在上一讲 Linux 网络编程的5种IO模型:阻塞IO与非阻塞IO中,对于其中的 阻塞/非阻塞IO 进行了 ...
- WC2019 填坑记
2019年1月8日 1.Luogu P2147 [SDOI2008]洞穴勘测 (LCT模板题&LCT学习) 2019年1月9日 2.LuoguP3203 [HNOI2010]弹飞绵羊 (LC ...
- 关于maven下,lombok的安装
1.首先下载lombok的jar包,可至https://mvnrepository.com/下载 2.双击即会自动扫描eclipse.exe,如图: 选择eclipse.exe,点击install/u ...