workerman 是一个php编写的通讯服务。之前的项目都是用它做数据接口服务

这次用它做一个简单的在线聊天室~

1.下载最新版本的workerman

可以去http://www.workerman.net 去下载

我这里将service 和 client 分开了两个文件夹,方便管理

大致的项目结构如下。

客户端:

客户端就简单了。一个简单的html代码。嵌入了一个 websocket 监听服务var ws, name, client_list={};

function connect() {

// 创建websocket

ws = new WebSocket("ws://192.168.0.88:2345");

// 当socket连接打开时,输入用户名

ws.onopen = onopen;

// 当有消息时根据消息类型显示不同信息

ws.onmessage = onmessage;

ws.onclose = function() {

console.log("连接关闭,定时重连");

connect();

};

ws.onerror = function() {

console.log("出现错误");

};

}

实现websocket的 打开,message的监听,以及close

1、当打开一个客户端,则立马弹出一个输入姓名的对话框function onopen(){

//console.log(name);

//var username=connect_id="";

if(!name)

{

name=prompt("请输入您的名字","");

if(!name || name=='null'){

name = '咕哒子';

}

}

$('#curuser').text(name);

data='{"type":"1","user":"'+name+'"}';

ws.send(data);

}

并将数据推送给服务端。type =1 代表登陆。

2、当收到消息时,判断消息类型,是群发消息 还是私聊消息。进而处理。

另外,每次用户有新用户登陆上来,都会 给各个客户端推送,用户列表。进行渲染function onmessage(e){

//console.log(e.data);

var data = eval("("+e.data+")");

var info=$('#chatinfo').html();

if(data.type==1)

$('#chatinfo').html(info+'
'+data.data);

else if(data.type==2)

{

// 在线用户列表 userinfo

$('#userinfo').html(data.data);

}

else if(data.type==3)

{

// 在线用户列表 个人信息

name=data.data.userinfo;

//console.log(data.data);

}

}

然后另外就是 每个用户发送消息的代码了。可以是私聊 ,也可以是群发$('#send').click(function(e){

var msg=$('#msg').val();

var tofriend=$('#tofriend').val();

var tofriendname=$('#tofriendname').val();

if(tofriend!="")

{

data='{"type":"3","user":"'+name+'","msg":"'+msg+'","friend_id":"'+tofriend+'","friendname":"'+tofriendname+'"}';

}else{

data='{"type":"2","user":"'+name+'","msg":"'+msg+'"}';

}

ws.send(data);

$('#msg').attr("value",'');

});

客户端差不多就是这样的了。

客户端,有几个坑 ,

坑1、变量名是 name 则刷新网页不会被重置,否则就会被重置。(后面查资料发现,这个name变量 是 window.name 。所以刷新网页 该值也不会被刷新掉)

坑2、js组数组,变量要用"" 最外层为'' 如:data='{"type":"1","user":"'+name+'"}'; 否则解析出问题。不能倒过来!

服务端:

服务端主要是workerman 组件 以及 使用 Channel分布式通讯组件 实现订阅 和集群推送 分组推送 以及私聊。

首先,当然是监听,启用一个worker的websocket监听// 创建一个Worker监听2346端口,使用websocket协议通讯

$ws_worker = new Worker("websocket://0.0.0.0:2345");

$channel_server = new Channel\Server('0.0.0.0', 2206);

// 启动4个进程对外提供服务

$ws_worker->count = 4;

$ws_worker->name="kinmoschat";

在workerman 监听启用的时候,进行 channel通讯的注册。$ws_worker->onWorkerStart=function($ws_worker)

{

// channel 客户端链接上 服务器

Channel\Client::connect('127.0.0.1',2206);

$event_name='私聊';

// 订阅 worker-

Channel\Client::on($event_name,function($event_data)use($ws_worker){

//print_r($event_data);

//print_r($ws_worker->connections);

$to_connect_id=$event_data['to_connection_id'];

$message=$event_data['content'];

foreach ($ws_worker->connections as $connection) {

if($connection->id==$to_connect_id)

{

$connection->send($message);

}

}

// if(!isset($ws_worker->connections[$to_connect_id]))

// {

// echo 'connect is not exist\n';

// return;

// }

// $to_connection=$ws_worker->connections[$to_connect_id];

// $to_connection->send($message);

});

// 订阅广播事件

$event_name = '广播';

// 收到广播 向所有客户端发送消息

Channel\Client::on($event_name,function($event_data)use($ws_worker){

//print_r($event_data);

$message=$event_data['content'];

foreach ($ws_worker->connections as $connection) {

$connection->send($message);

}

});

};

注册两个事件,一个广播事件,一个私聊事件,用以上线通知的广播,以及群发消息。私聊 就是私聊了。。这里,还可以做 分组的群发。不过,这个版本还未实现。

然后是针对,客户端链接的回调。$ws_worker->onConnect=function($connection){

$connection->id = md5($connection->id."_".time()."_".rand(10000,99999));

};

这里,客户端回调,我会将客户端的 connectid修改掉。一个简单的md5 主要是为了防止 流水id太容易被利用吧。。

然后,整个项目的主体,服务端消息的处理回调。

针对每个进来的客户端,分配一个唯一 id

维护一个 connectid=>user 的关系表

由于开启了多个进程导致 存到 session中无效,故而 打算存到 数据库中

断开链接的时候,删除数据$ws_worker->onMessage = function($connection, $data)

{

$res=array('code'=>200, 'msg'=>'ok', 'data'=>null,'type'=>1);

// 向客户端发送hello $data

//print_r($data);

$data=json_decode($data,true);

//print_r($data);

if(!isset($data['type'])||empty($data['type']))// type 1 2

{

$res=array('code'=>301, 'msg'=>'消息包格式错误', 'data'=>null);

}else{

switch ($data['type']) {

case '1': // 客户端上线消息

//print_r($connection->id);

if(!isset($data['user'])||empty($data['user']))

{

$res=array('code'=>301, 'msg'=>'消息包格式错误', 'data'=>null);

break;

}

// 维护一个数组 保存 用户 connection_id => user

$dsn='mysql:host=127.0.0.1;dbname=kinmoschat;';

$pdo=new PDO($dsn,'root','123456');

//准备SQL语句

$sql = "INSERT INTO `user`(`connect_id`,`username`) VALUES (:connect_id,:username)";

//调用prepare方法准备查询

$stmt = $pdo->prepare($sql);

//传递一个数组为预处理查询中的命名参数绑定值,并执行SQL

$stmt->execute(array(':connect_id' => $connection->id,':username' => $data['user']));

//获取最后一个插入数据的ID值

//echo $pdo->lastInsertId() . '
';

// 向自己推送一条消息

$res2['type']=3;// 系统信息

$res2['data']=array('userinfo' =>$data['user']);// 系统信息

$connection->send(json_encode($res2));

$msg="用户 ".$data['user']." 上线了~~";

$res['data']=$msg;

break;

case '2': // 客户端群发送消息

if(!isset($data['user'])||empty($data['user'])||!isset($data['msg'])||empty($data['msg']))

{

$res=array('code'=>301, 'msg'=>'消息包格式错误', 'data'=>null);

break;

}

$msg="用户 ".$data['user']."说:".$data['msg'];

$res['data']=$msg;

break;

case '3': // 客户端私聊

if(!isset($data['user'])||empty($data['user'])||!isset($data['msg'])||empty($data['msg'])||!isset($data['friend_id'])||empty($data['friend_id']))

{

$res=array('code'=>301, 'msg'=>'消息包格式错误', 'data'=>null);

break;

}

$msg="用户 ".$data['user']."对您说:".$data['msg'];

$res['data']=$msg;

$res['type']=1;// 聊天消息

$res1=json_encode($res);

// 推送给单个用户

$event_name = '私聊';

Channel\Client::publish($event_name, array(

'content' => $res1,

'to_connection_id' =>$data['friend_id']

));

// 另外还要给自己推条消息

$msg="您对 ".$data['friendname']."说:".$data['msg'];

$res['data']=$msg;

$res['type']=1;// 聊天消息

$res2=json_encode($res);

Channel\Client::publish($event_name, array(

'content' => $res2,

'to_connection_id' =>$connection->id

));

return;

break;

default:

# code...

break;

}

}

$res['type']=1;// 聊天消息

$res=json_encode($res);

// 广播给所有客户端

$event_name = '广播';

Channel\Client::publish($event_name, array(

'content' => $res

));

$dsn='mysql:host=127.0.0.1;dbname=kinmoschat;';

$dbh=new PDO($dsn,'root','123456');

$stmt=$dbh->query('SELECT connect_id,username FROM user');

$row=$stmt->fetchAll();

$uerHtml="";

foreach ($row as $key => $value) {

$uerHtml.=''.$value['username'].'
';

}

//print_r($row);

$res1['type']=2;// 用户消息

$res1['data']=$uerHtml;

$res1=json_encode($res1);

$event_name = '广播';

Channel\Client::publish($event_name, array(

'content' => $res1

));

};

这里会将每个用户的 connectid=>name 存入数据库。。

当收到一条 上线消息的时候,广播给所有用户。

收到一条群发消息。。广播给所有客户端。

收到一条私聊消息。则单个推送给自己以及发送的人。

监听 客户端关闭事件,当客户端关闭,删除用户表相关记录// 关闭链接 将数据库中的该数据删除

$ws_worker->onClose=function($connection)

{

//echo 3233;

$dsn='mysql:host=127.0.0.1;dbname=kinmoschat;';

$pdo=new PDO($dsn,'root','123456');

$sql="delete from user where connect_id='".$connection->id."'";

//print_r($sql);

$pdo->exec($sql);

};

更多workerman知识请关注workerman教程栏目。

php使用workerman实战,使用workerman实现在线聊天的方法相关推荐

  1. PHP+Workerman即时通讯技术:在线聊天/客服/访客功能

    PHP+Workerman即时通讯技术:在线聊天/客服/访客功能 1:客服端 2:客户端 3:多访客 4:聊天表情 客服端 http://videolaravel.zwzgjl.com/index.p ...

  2. 无人驾驶实战第一课--七月在线

    无人驾驶实战第一课--七月在线 概述 无人驾驶分级 L4级架构 自动驾驶软件概述 mark一下,希望坚持下去 概述 未来的趋势是无人驾驶.传感器,车辆,算法都有非常大的空间. 无人驾驶分级 L0 ,手 ...

  3. php 即时聊天 实现方法,谈谈利用workerman实现即时聊天功能的方法

    本篇文章给大家介绍一下使用workerman实现即时聊天的方法.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 开发文档:http://doc2.workerman.net/ 下载服 ...

  4. 实战 | 使用 Python 开发一个在线聊天室

    点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 云想衣裳花想容,春风拂槛露华浓. ...

  5. 【云原生之Docker实战】使用Docker部署Fiora在线聊天室平台

    [云原生之Docker实战]使用Docker部署Fiora在线聊天室平台 一.Fiora介绍 1.Fiora简介 2.Fiora功能 二.检查宿主机系统版本 三.检查本地docker环境 1.检查do ...

  6. React全Hook项目实战在线聊天室历程(三):加个音乐直播?

    前情提要: React全Hook项目实战在线聊天室历程(一):基本功能 React全Hook项目实战在线聊天室历程(二):引用与话题功能 正文 聊天应该有什么?背景音乐,茶与酒,零食,后两个我是没法实 ...

  7. 【云原生之Docker实战】使用Docker部署Web在线聊天室Rocket.Chat

    [云原生之Docker实战]使用Docker部署Web在线聊天室Rocket.Chat 一.Rocket.Chat介绍 二.检查本地系统环境 1.检查系统版本 2.检查docker版本 3.检查doc ...

  8. 实战|使用 Python 开发一个在线聊天室

    「来源: |Python爬虫与数据挖掘 ID:crawler_python」 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 云想衣裳花想容,春风拂槛露 ...

  9. Java创建服务端和客户端基础(一)多人在线聊天程序实战基础

    基于Java一步步实现多人在线聊天!(持续更新中) 文章目录 ⚡前言

最新文章

  1. mongodb主从设置,capped collections等常用命令集合
  2. OPENCV图像创建,保存和复制
  3. 5G NGC — 会话管理模型 — PDU Session
  4. 在Visual Studio 2010/2012中 找不到创建WebService的项目模板
  5. 第1章:初始C#及其开发环境
  6. java基础不好框架能学会吗_转行Java能学会吗?零基础学习Java的学习路线
  7. 自我总结 (三) --(Java Web学习)
  8. linux cookie 地址,SYN Cookie原理及其在Linux内核中的实现
  9. android批处理脚本,BAT批处理一键生成APK包脚本分享
  10. Nginx基本功能及其原理
  11. AIX安装中文语言包
  12. 堂娜·哈拉维:赛博格宣言
  13. 【总结】大规模数据(300万条)测试时,需要注意的问题。
  14. MacBook Pro 用户学会这 5 个小技巧,让你的 Touch Bar 更好用
  15. IE8变成IE7的显示方式
  16. SQL获得当前时间函数(MySQL)
  17. 数据通信与计算机网复习题,数据通信与计算机网络 复习题总.doc
  18. C / C++头文件大全
  19. Taro React组件使用(1) —— Overlay 遮罩层【渐入渐出动画遮罩层】
  20. 关于Canvas画布大小问题

热门文章

  1. mysql查看正在执行的sql语句
  2. java中缀表达式转后缀表达式(逆波兰算法)
  3. Linux下DNS简单部署(主从域名服务器)
  4. 用Servlet获取表单数据
  5. 理解RESTful架构
  6. 10倍效率的程序员的好习惯,你有几个?
  7. android中设置控件获得焦点 (转)
  8. CV00-03-CV基本操作2
  9. 区块链和智能合约的关系
  10. vim block vim_如何不再害怕Vim