workerman 实践 及 不能多人连接的问题
官网:https://www.workerman.net/
手册地址:https://www.workerman.net/doc
追加内容:
请在开发前多读读 开发必读http://doc.workerman.net/development/before-development.html
追加内容结束
第一次使用workerman,目标要求实现客户端与服务器1对1的通信。
第一次尝试:
前端js
//文档地址
//http://doc.workerman.net/getting-started/simple-example.html // 假设服务端ip为127.0.0.1
ws = new WebSocket("ws://127.0.0.1:2000");
ws.onopen = function() {
alert("连接成功");
ws.send('tom');
alert("给服务端发送一个字符串:tom");
};
ws.onmessage = function(e) {
alert("收到服务端的消息:" + e.data);
};
后端 php
//文档地址
//http://doc.workerman.net/getting-started/simple-example.html <?php
use Workerman\Worker;
require_once __DIR__ . '/Workerman/Autoloader.php'; // 注意:这里与上个例子不同,使用的是websocket协议
$ws_worker = new Worker("websocket://0.0.0.0:2000"); // 启动4个进程对外提供服务
$ws_worker->count = 4; // 当收到客户端发来的数据后返回hello $data给客户端
$ws_worker->onMessage = function($connection, $data)
{
// 向客户端发送hello $data
$connection->send('hello ' . $data);
}; // 运行worker
Worker::runAll();
命令行: 代码部署完毕之后需要在命令行中启动
// 文档地址
// http://doc.workerman.net/install/start-and-stop.html // 以下运行方式任选一种
// 线上环境需要以守护进程方式启动 并且要加心跳[如果不会请百度] //以debug(调试)方式启动
php start.php start //以daemon(守护进程)方式启动
php start.php start -d
总结:
1.在测试中发现本方法如果只开启一个进程只能够连接一个客户端,超出一个客户端的连接会出现连接失败,需要等待上一个连接断开之后才能够进行下一个连接[四个进程只能连接四个客户端],但是文档说单个进程最多可以支持5w连接数,手册查找原因【本答案未必准确,百度未找到类似答案 仅作参考】:
追加:
1.不能多人连接是因为php代码出现了报错,如果不能多人连接请解决所有错误
2.不要使用 sleep exit die 函数 导致进程停止或结束
// 文档地址
// http://doc.workerman.net/development/before-development.html //三、区分主进程和子进程 //有必要注意下代码是运行在主进程还是子进程,一般来说在Worker::runAll();调用前运行的代码都是在主进程运行的,onXXX回调运行的代码都属于子进程。注意写在Worker::runAll();后面的代码永远不会被执行。 //例如下面的代码 require_once __DIR__ . '/Workerman/Autoloader.php';
use Workerman\Worker; // 运行在主进程
$tcp_worker = new Worker("tcp://0.0.0.0:2347");
// 赋值过程运行在主进程
$tcp_worker->onMessage = function($connection, $data)
{
// 这部分运行在子进程
$connection->send('hello ' . $data);
}; Worker::runAll(); //注意: 不要在主进程中初始化数据库、memcache、redis等连接资源,因为主进程初始化的连接可能会被子进程自动继承(尤其是使用单例的时候),所有进程都持有同一个连接,服务端通过这个连接返回的数据在多个进程上都可读,会导致数据错乱。同样的,如果任何一个进程关闭连接(例如daemon模式运行时主进程会退出导致连接关闭),都导致所有子进程的连接都被一起关闭,并发生不可预知的错误,例如mysql gone away 错误。 //推荐在onWorkerStart里面初始化连接资源。
2.当开启多进程的时候,多个客户端进行连接会导致用户发送给服务器的消息会被服务器发送给所有用户
第二次尝试:
第一次尝试由于不支持多人连接,所以百度及文档查找如何进行多人连接,如果进行多人连接,那么就需要使用uid进行标示用户,来给不同的用户发送消息,实现一对一的消息
php
<?php
use Workerman\Worker;
require_once __DIR__ . '/Workerman/Autoloader.php';
//
$ws_worker = new Worker('websocket://127.0.0.1:2000');
// // 新增加一个属性,用来保存uid到connection的映射(uid是用户id或者客户端唯一标识)
$worker->uidConnections = array();
// 手册说只能一个
$ws_worker->count = 1; // 当收到客户端发来的数据后返回hello $data给客户端
$ws_worker->onMessage = function ($connection, $data) {
global $ws_worker;
// 客户端的第一次消息当作获取uid
// 判断当前客户端是否已经验证,即是否设置了uid
// 这里只是简单的把 $connection->id 当作他的uid 因为 connection->id 是唯一的
if (!isset($connection->uid)) {
$connection->uid = $connection->id;
$ws_worker->uidConnections[$connection->uid] = $connection; return $connection->send($connection->uid);
}
//获取uid
list($uid, $message) = explode(':', $data);
//判断id是否存在 然后发送消息
if (isset($ws_worker->uidConnections[$uid])) {
$connection = $ws_worker->uidConnections[$uid];
$connection->send("自定义消息内容");
}
}; // 运行worker
Worker::runAll();
js
ws = new WebSocket("ws://127.0.0.1:2000");
var uid = "";
ws.onmessage = function (e) {
//设置uid
if(uid == ""){
uid = e.data;
return ;
}
//实现逻辑代码区域
//....
}
总结:
1.实现了多用户连接[与进程数量无关]
2.显示单个用户与服务器的一对一的消息
workerman 实践 及 不能多人连接的问题的更多相关文章
- 百度APP移动端网络深度优化实践分享(二):网络连接优化篇
本文由百度技术团队“蔡锐”原创发表于“百度App技术”公众号,原题为<百度App网络深度优化系列<二>连接优化>,感谢原作者的无私分享. 一.前言 在<百度APP移动端网 ...
- Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务(转载6)
Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务 一.引言 今天本来没有打算写这篇文章,但是,今天测试Redis的时候发现了两个问题 ...
- SSH开发实践part2:双向1-N连接配置
1 OK,上一篇已经介绍了项目开发的前期准备工作,具体内容可以参考:http://www.cnblogs.com/souvenir/p/3783686.html 按照开发步骤,我们现在已经可以开始进行 ...
- 高性能C++网络库libtnet实践:comet单机百万连接挂载测试
最近在用go语言做一个挂载大量长连接的推送服务器,虽然已经完成,但是内存占用情况让我不怎么满意,于是考虑使用libtnet来重新实现一个.后续我会使用comet来表明推送服务器. 对于comet来说, ...
- Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务
一.引言 今天本来没有打算写这篇文章,当初我感觉使用这个工具应该很简单,下载的过程也不复杂,也没有打算记录下来.但是在使用的过程中还是出现了一些问题,为了给第一次使用Redis Desktop Man ...
- python编程:从入门到实践--项目1-外星人入侵_学习笔记_源码
这里有九个.py文件,在工作的间隙,和老板斗智斗勇,终于完成了,实现了游戏的功能,恰逢博客园开通,虽然是对着书上的代码敲了一遍,但是对pygam这个库的了解增加了一些,作为一个python初学者,也作 ...
- TCP长连接实践与挑战
点这里立即申请 本文介绍了tcp长连接在实际工程中的实践过程,并总结了tcp连接保活遇到的挑战以及对应的解决方案. 作者:字节跳动终端技术 --- 陈圣坤 概述 众所周知,作为传输层通信协议,TCP是 ...
- .Net程序员学用Oracle系列(8):触发器、作业、序列、连接
1.触发器 2.作业 2.1.作业调度功能和应用 2.2.通过 DBMS_JOB 来调度作业 3.序列 3.1.创建序列 3.2.使用序列 & 删除序列 4.连接 4.1.创建连接 4.2.使 ...
- 百度APP移动端网络深度优化实践分享(一):DNS优化篇
本文由百度技术团队“蔡锐”原创发表于“百度App技术”公众号,原题为<百度App网络深度优化系列<一>DNS优化>,感谢原作者的无私分享. 一.前言 网络优化是客户端几大技术方 ...
随机推荐
- tp5 模型中 关联查询(省去了foreach写法)
1.控制器中 $list = Userlawsbook::where($where)->with('lawsbook')->paginate(7); // 此处查出来为数组对象 dump ...
- 【java测试】Junit、Mock+代码覆盖率
原文见此处 单元测试是编写测试代码,用来检测特定的.明确的.细颗粒的功能.单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的. 单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代 ...
- 定时任务-Quartz(热部署、冷部署)
一.配置Quartz.xml <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context ...
- AttributeError:module 'keras.engine.topology' has no attribute 'load_weights_from_hdf5_group_by_name
在jupyter notebooks上运行tensorflow-keras的Mask R-CNN时遇到如下错误: 参考博客中写了两种解决方案: 解决方案一:报错是由于keras版本不对造成的.load ...
- 码云上webide怎么提交
修改后想提交,它会提示:“暂存文件后才能提交”, 我拿放大镜找遍了整个界面也没找到“暂存”按钮, 原来,文件旁边那个+号就是暂存,好歹鼠标方式去之后给个tip,服了. 点一下这个加号,提交按钮就可用了 ...
- 什么是 AIDL 以及如何使用
①aidl 是 Android interface definition Language 的英文缩写,意思 Android 接口定义语言.②使用 aidl 可以帮助我们发布以及调用远程服务,实现跨进 ...
- SVN+MAVEN项目打包
题记:项目打包bash脚本 环境准备 maven版本:3.5.2 mvn -v #查看maven的版本信息 svn版本:1.4.0 svn --version #查看svn版本信息 1.update_ ...
- 用泛型方法Java从实体中提取属性值,以及在泛型方法中的使用
public <T> T getFieldValue(Object target, String fieldName, Class<T> typeName) { try { O ...
- [笔记] 基于nvidia/cuda的深度学习基础镜像构建流程 V0.2
之前的[笔记] 基于nvidia/cuda的深度学习基础镜像构建流程已经Out了,以这篇为准. 基于NVidia官方的nvidia/cuda image,构建适用于Deep Learning的基础im ...
- CTF—攻防练习之HTTP—SQL注入(SSI注入)
主机:192.168.32.152 靶机:192.168.32.161 ssI是赋予html静态页面的动态效果,通过ssi执行命令,返回对应的结果,若在网站目录中发现了.stm .shtm .shtm ...