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优化>,感谢原作者的无私分享. 一.前言 网络优化是客户端几大技术方 ...
随机推荐
- LeetCode 144. 二叉树的前序遍历(Binary Tree Preorder Traversal)
题目描述 给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 解题思路 由 ...
- R语言:读入txt文件中文文本出现乱码解决方案
下载安装 readr 因为使用内置函数 read.table() 读入应该是格式不符合要求会报错 library(readr) help(package="readr") 可以使用 ...
- Android jni/ndk编程一:jni初级认识与实战体验
Android平台很多地方都可以看到jni的身影,比如之前接触到一个投屏的项目,主要的代码是c/c++写的,然后通过Jni供Java层调用;另外,就拿Android系统中的Service来说,很多的S ...
- uboot下如何读写rtc pcf2127的寄存器?
一. pcf2127简介 pcf2127是实时时钟计数器模块,支持两种接口,i2c和spi,笔者以i2c为例 二. pcf2127的读写操作时序 2.1 写操作 根据i2c的规范https://www ...
- IOS input框轻点无效修复方法
FastClick.prototype.focus = function(targetElement) { targetElement.focus();//加入这一句话就OK了 };
- 根据XML文件 生成 java类
最近一直在做关于webservice 的项目,这种项目最麻烦的就是根据对方的要求产生XML,文档里面虽然有XML结构,但是要转化为java里面的实体实在费劲, 有个自动化的工具就好了,半自动化也好,省 ...
- appium+python+android+HTMLTestRunner使用过程中的问题
1:问:appium客户端刚发布了一版新的,我想升级可以吗?答:建议对于刚发布的新版本不要立即升级,因为客户端每升级一版它肯定会去增加和删减一些语句.所以不建议立即升级. 应该先采取调研的态度看 ...
- gin框架教程:代码系列demo地址
gin框架教程代码地址: https://github.com/jiujuan/gin-tutorial demo目录: 01quickstart 02parameter 03route 04midd ...
- Linux C/C++基础——二级指针做形参
1.二级指针做形参 #include<stdio.h> #include<stdlib.h> void fun(int **temp) { *temp=(int*)malloc ...
- amh 操作
挂在分区到/home 迁移数据库/usr/local/mysql/data 到/home/data目录 504 卡死 进入kangle后台,选扩展,再选中扩展里的命令选项,修改PHP-NTS的协议为f ...