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优化>,感谢原作者的无私分享. 一.前言 网络优化是客户端几大技术方 ...
随机推荐
- Linux 下搭建Git 服务器详细步骤
参考: https://www.cnblogs.com/dee0912/p/5815267.html#_label0 https://blog.csdn.net/carfge/article/deta ...
- spark streaming 4: DStreamGraph JobScheduler
DStreamGraph有点像简洁版的DAG scheduler,负责根据某个时间间隔生成一序列JobSet,以及按照依赖关系序列化.这个类的inputStream和outputStream是最重要的 ...
- PL/SQL的命令行窗口中执行脚本
注意脚本路径中不能有空格, 格式如下:SQL>@D:\1211_Export\all.sql 备注: @后面接本地sql文件的路径及执行文件
- Response.AddHeader("Content-Disposition", "attachment; filename=" + file.Name) 中文显示乱码
如果file.Name为中文则乱码.解决办法是方法1:response.setHeader("Content-Disposition", "attachment; fil ...
- JS编程规范
在第一家公司用C++时,公司有着严格的代码规范,甚至到了严苛的地步,现在回想起来,对它充满感激.一个好的习惯让你收益终身. 之后使用JS/TS却没有为自己定一套编程规范,所幸为时不晚,在这里参考air ...
- 排查python内存泄露中几个工具的使用
本文主要介绍3个工具:pdb,objgraph,以及pympler. 1.pdb pdb是专门用于python代码调试,模仿gdb. 使用pdb可以查看堆栈,打印变量等. 这里介绍的是命令行下的pdb ...
- 图片加载框架之ImageLoader
Android开发中,多少会接触到异步加载图片,或者加载大量图片的问题,而加载图片我们常常会遇到许多的问题,比如说图片的错乱,OOM等问题,对于这些问题解决起来会比较吃力,比较著名的就是Univers ...
- Ironic 裸金属管理服务的网络模型
目录 文章目录 目录 Bare-Metal networking in Neutron 核心网络类型 网络拓扑 抽象网络拓扑图 Neutron Implementation Neutron 了解裸金属 ...
- 小D课堂 - 新版本微服务springcloud+Docker教程_2_01传统架构演进到分布式架构
笔记 第二章 架构演进和分布式系统基础知识 1.传统架构演进到分布式架构 简介:讲解单机应用和分布式应用架构演进基础知识 (画图) 高可用 LVS+keepalive :负载均衡的知识点 1. ...
- RxJava2实战---第六章 条件操作符和布尔操作符
RxJava2实战---第六章 条件操作符和布尔操作符 RxJava的条件操作符主要包括以下几个: amb():给定多个Observable,只让第一个发射数据的Obsrvable发射全部数据. de ...