今天是第二次重新开发使用layim和Gatewayworker,但是由于第一次没有写文档,导致这一次就跟第一次一样,一头雾水,重新开始看文档研究,导致遇到一个瓶颈,怎么都过不去。所以,以这篇文章开始,以后所有的知识点,全部写上文档。

首先如果是快速入手的快,直接从http://www.workerman.net/windows下载,worker。然后解压放到项目中去。

,除了以上这三个文件,其他文件不需要做任何修改。

1 Events.php

这里面内容将是操控数据库和实现页面内容返回的地方,所以可以在这里面自定义任何方法。

<?php
/**
* This file is part of workerman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/ /**
* 用于检测业务代码死循环或者长时间阻塞等问题
* 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload
* 然后观察一段时间workerman.log看是否有process_timeout异常
*/
//declare(ticks=1); // 自动加载类
use \GatewayWorker\Lib\Gateway;
use \GatewayWorker\Lib\DbConnection;
/**
* 主逻辑
* 主要是处理 onConnect onMessage onClose 三个方法
* onConnect 和 onClose 如果不需要可以不用实现并删除
*/
class Events
{
public static $db;
public static $uuid = [];
public static $clientid = []; public static function onWorkerStart()
{
self::$db = new DbConnection('xxx', '3306', 'xxx', xxx', 'xxx');
} /**
* 当客户端连接时触发
* 如果业务不需此回调可以删除onConnect
*
* @param int $client_id 连接id
*/
public static function onConnect($client_id){
// Gateway::sendToClient($client_id, json_encode($noonline));
} /**
* 当客户端发来消息时触发
* @param int $client_id 连接id
* @param mixed $message 具体消息
*/
public static function onMessage($client_id, $message)
{ $data = json_decode($message,true);
switch($data['type']) {
//当有用户上线
case 'reg':
//绑定uid 用于数据分发
$uid = $data['data']['id'];
Gateway::bindUid($client_id, $uid);
self::$clientid[$client_id] = $uid; //如果数组中不存在键值uid,那么表示是第一次登陆,更新数据库
if(!isset(self::$uuid[$uid])){
self::$uuid[$uid] = $uid;
self::$db->update('im_user_baseInfo')->cols(array('status'=>1))->where('id='.$uid)->query();
}
break; case 'chatMessage':
//正常聊天 $to_user = $data['data']['to']['id'];
$from_user = $data['data']['mine']['id'];
$time = time();
$content = quotationMarks($data['data']['mine']['content']); $msg = array(
'username'=> $data['data']['mine']['username'],//消息来源用户名
'avatar'=> $data['data']['mine']['avatar'],
'id'=> $from_user,//消息的来源ID(如果是私聊,则是用户id,如果是群聊,则是群组id)
'content'=> $content,
'type'=> 'friend',//聊天窗口来源类型,从发送消息传递的to里面获取
'mine'=> false,//是否我发送的消息,如果为true,则会显示在右方
'timestamp'=> date('Y-m-d h:i:s',$time),
'emit'=> 'chatMessage'
);
//发送给自己的,同客户端同步
$msg2 = array(
'username'=> $data['data']['mine']['username'],//消息来源用户名
'avatar'=> $data['data']['mine']['avatar'],
'id'=> $to_user,//消息的来源ID(如果是私聊,则是用户id,如果是群聊,则是群组id)
'content'=> $content,
'type'=> 'friend',//聊天窗口来源类型,从发送消息传递的to里面获取
'mine'=> true,//是否我发送的消息,如果为true,则会显示在右方
'timestamp'=> date('Y-m-d h:i:s',$time),
'emit'=> 'sendme'
);
$sql = array(
'from_user'=>$from_user,
'to_user'=>$to_user,
'type'=>1,//目前默认都是朋友
'content'=>$content,
'msg_type'=>1,//1:文本 2:资源(图片,文件等)
'add_time'=>$time,
'is_read'=>1,//已经查看
); //判断是否在线
if (Gateway::isUidOnline($to_user)) {
Gateway::sendToUid($to_user, json_encode($msg));
self::$db->insert('im_message')->cols($sql)->query();
}
else
{
//如果对方离线,发送系统消息
$sql['is_read'] = 0;
self::$db->insert('im_message')->cols($sql)->query(); $noonline = array(
'emit'=>'status',
'fromid'=>-2,
'id'=>-2,
'status'=>0,
);
Gateway::sendToClient($client_id, json_encode($noonline));
} //根据uid获取其他客户端的client_id
$from_client_list = Gateway::getClientIdByUid($from_user); unset($from_client_list[array_search($client_id,$from_client_list)]);
foreach ($from_client_list as $from_client){
Gateway::sendToClient($from_client, json_encode($msg2));
}
break; //查询是否在线的状态
case 'status':
$to_user = $data['data']['id'];
$noonline = array(
'emit'=>'status',
'fromid'=>-2,
'id'=>-2,
'status'=>0
);
if (Gateway::isUidOnline($to_user)) {
$noonline['status'] = 1;
}
Gateway::sendToClient($client_id, json_encode($noonline)); break; //修改聊天记录为已读状态
case 'isread':
$username = quotationMarks($data['data']['name']);
$uid = quotationMarks($data['data']['mid']);
$from_user = self::getUserinfoByname($username); //改变消息的已读状态
if(!empty($from_user) && !empty($uid)) self::changeIsread($from_user,$uid,1);
break;
} } /**
* 当用户断开连接时触发
* @param int $client_id 连接id
*/
public static function onClose($client_id)
{
$id = self::$clientid[$client_id];
unset(self::$clientid[$client_id]);
//如果长度等于0,说明绑定该uid的所有客户端都下线了
if(count(Gateway::getClientIdByUid($id)) == 0){
unset(self::$uuid[$id]);
self::$db->update('im_user_baseInfo')->cols(array('status'=>0))->where('id='.$id)->query();
}
// var_export(self::$clientid); } /**
* 查询该用户名对应的用户
* @param $username
* @return mixed
*/
public static function getUserinfoByname($username){
$result = self::$db->select('id')->from('im_user_baseInfo')->where("username= '$username' ")->column();
return $result[0];
} /**
* Mobile将消息设置为已读状态
* @param $from_user
* @param $to_user
* @param $is_read
*/
public static function changeIsread($from_user,$to_user,$is_read){
$sql = "UPDATE im_message SET is_read = $is_read WHERE from_user = $from_user AND to_user = $to_user";
self::$db->query($sql);
} }
/**
* 数据接收正则匹配,去掉字符串中的单引号和双引号
* add by fpc time:2017-03-29
*/
function quotationMarks($str){
// 正则表达式匹配中文(UTF8编码)
if(preg_match_all('/\'(.*?)\'/',$str)){
$str = str_replace("\'",'',$str);
if(preg_match_all('/\"(.*?)\"/',$str)){
$str = str_replace('\"','',$str);
}
return trim($str);
}else{
return addslashes(trim($str));
}
}

2start_businessworker.php

3start_gateway.php

4客户端

总共就以上这些代码,以上代码仅在windows下的代码,今天遇到一个问题,由于文件和方法是从linux移动过来的,所以调试的时候就出现了一下问题

服务器一直是可以的,但是使用

var socket = new WebSocket('ws://192.168.0.188:8484');打开的时候,就一直连接不上,原因就在于在start_gateway.phpz这个文件中,
$gateway = new Gateway("websocket://0.0.0.0:8484");这一句,linux是    tcp://..........  windows是websocket。
接下来就是无限发挥的时刻了 如果是https的服务器,那么使用
var socket = new WebSocket('wss://192.168.0.188:8484');

第二部分

摘要:在一个服务器上可以有多个 WebSocket部署

说明:第二个使用的是https

当我在同一个服务器上,使用workman部署第二个websocket的时候如图所示为了防止端口号冲突,要修改端口号与以第一个部署的服务器的端口号全部不一样

因为使用了https,与http的区别就是增加了这两层代码

在前台的js中

var socket = new WebSocket('wss://www.xxx.com:7272');  wss://域名+端口号,端口号要注意和gate的一致

layim和Gatewayworker组合的实时通讯的更多相关文章

  1. 使用Websocket框架之GatewayWorker开发电商平台买家与卖家实时通讯

    前段时间公司提了一个新的需求,在商品的详情页要实现站内买家和商品卖家实时通讯的功能以方便沟通促成交易,要开发此功能当时首先考虑到的就是swoole和workerman了,从网上大概了解了一下关于这两款 ...

  2. 基于TP5使用Websocket框架之GatewayWorker开发电商平台买家与卖家实时通讯

    https://www.cnblogs.com/wt645631686/p/7366924.html 前段时间公司提了一个新的需求,在商品的详情页要实现站内买家和商品卖家实时通讯的功能以方便沟通促成交 ...

  3. PHP基于TP5使用Websocket框架之GatewayWorker开发电商平台买家与卖家实时通讯

    前段时间公司提了一个新的需求,在商品的详情页要实现站内买家和商品卖家实时通讯的功能以方便沟通促成交易,要开发此功能当时首先考虑到的就是swoole和workerman了,从网上大概了解了一下关于这两款 ...

  4. Android IOS WebRTC 音视频开发总结(六二)-- 大数据解密国外实时通讯行业开发现状

    本文主要介绍国外实时通讯行业现状,文章最早发表在我们的微信公众号上,详见这里,欢迎关注微信公众号blackerteam,更多详见www.blackerteam.com 上篇文章我们采用百度搜索指数来分 ...

  5. Android IOS WebRTC 音视频开发总结(六一)-- 大数据解密国内实时通讯行业开发现状

    本文主要介绍国内实时通讯行业现状,文章最早发表在我们的微信公众号上,详见这里,欢迎关注微信公众号blackerteam,更多详见www.blackerteam.com 这几年移动互联网发展势头很猛,与 ...

  6. [渣译文] SignalR 2.0 系列:SignalR的高频实时通讯

    原文:[渣译文] SignalR 2.0 系列:SignalR的高频实时通讯 英文渣水平,大伙凑合着看吧…… 这是微软官方SignalR 2.0教程Getting Started with ASP.N ...

  7. B/S(Web)实时通讯解决方案

    B/S的实时通讯实现起来比较麻烦,因为http协议是无状态的,导致一些实时消息通知和聊天等功能比较难以实现,本文主要简述几种自己之前常用的几种方式. 1.传统的HTTP协议是无状态的 传统的HTTP协 ...

  8. 仿PC版微信的练手项目(可实时通讯)

    仿PC版微信的DEMO 本项目是由一个仿PC版微信的vue前端项目,和一个使用leancloud进行数据存储的.提供WebSocket的node后端项目构成. 本项目使用的技术栈:vue + vue- ...

  9. (二): 基于ZeroMQ的实时通讯平台

    基于ZeroMQ的实时通讯平台 上篇:C++分布式实时应用框架 (Cpp Distributed Real-time Application Framework)----(一):整体介绍 通讯平台作为 ...

随机推荐

  1. iOS 打包生成ipa文件(使用终端命令打包)

    1. 打开终端 2.在终端输入cd +空格 把工程文件直接拖到终端,然后回车 3. 在终端输入xcodebuild,回车 然后你可以发现工程文件里多了一个build文件夹 在build文件夹中,有一个 ...

  2. Struts2 看1

    Struts2部分 1. JavaEE软件三层结构和MVC的区别? JavaEE软件三层机构是由sun公司提供JavaEE开发规范的:Web层(表现层).业务逻辑层.数据持久层.[其中WEB层会使用前 ...

  3. 长城防火墙(GFW)

    一.简介 中国防火长城,官方名为金盾工程,是由政府运作的一个互联网审查监控项目.在其管辖互联网内部建立的多套网络审查系统的总称,包括相关行政审查系统.其英文名称Great Firewall of Ch ...

  4. Spring学习大纲

    1.BeanFactory 和 FactoryBean? 2.Spring IOC 的理解,其初始化过程? 3.BeanFactory 和 ApplicationContext? 4.Spring B ...

  5. Java50道经典习题-程序26 求星期

    题目:请输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续 判断第二个字母.分析:用情况语句比较好,如果第一个字母一样,则判断用情况语句或if语句判断第二个字母.周一至周日的英文单词 ...

  6. WPF之MVVM模式(2)

    我们都想追求完美 Every view in the app has an empty codebehind file, except for the standard boilerplate cod ...

  7. winform ComBox绑定数据

    初始化数据: List<KeyValuePair<string, string>> list: ComBox1.ValueMember = "Key";Co ...

  8. kylin 连接 hortonworks 中的 hive 遇到的问题

    用 hortonworks(V3.1.0.0) 部署了 ambari (V2.7.3),用 ambari 部署了 hadoop 及 hive. 1.  启动 kylin(V2.6)时,遇到如下问题: ...

  9. fseek函数

    函数名:fseek函数 头文件:#include<stdio.h> 功能:把与fp有关的文件位置指针放到一个指定位置. 格式:  int fseek(FILE *stream, long ...

  10. Elaxia的路线

    Elaxia的路线 求无向图中,两对点间最短路的最长公共路径. 四遍spfa标出每条边的标记,然后用拓扑排序跑dp即可. exp:拓扑排序可以跑DAG上的dp. #include <cstdio ...