PHP聊天室框架

https://www.workerman.net/workerman-chat

PHP聊天室框架

workerman-chat是一个以workerman作为服务器容器,使用PHP开发的基于Websocket协议的一个可分布式部署的聊天室框架。

workerman-chat采用gateway workers 进程模型。gateway只负责网络IO,全异步非阻塞,每个gateway进程都可以同时接受上万客户端连接。 workers采用的是PHP开发者所熟悉的同步模型,并提供了开发者基本的接口 onConnect、onMessage、onClose、sendToClient、sendToAll等方法。 开发者只要在onConnect、onMessage、onClose三个方法中添加上自己的业务逻辑即可,开发维护非常简单。

由于采用的是gateway workers 进程模型,gateway和workers之间是无状态的,gateway和workers可以分别部署在不同的物理机上,所以扩容和升级都非常方便。 workerman-chat也非常适合游戏后台开发。

查看php聊天室demo请点击这里

下载

下载PHP 聊天室框架

Fork on Github  下载ZIP压缩文件 下载55619次

特性

  • 使用PHP开发
  • PHP多进程
  • gateway workers进程模型
  • 支持libevent事件轮询库,支持高并发
  • 默认使用Websocket协议,更小带宽,更好性能
  • 支持分布式部署,可横向扩容
  • 客户端跨浏览器支持(需要浏览器支持html5或者flash)
  • 多房间支持
  • 支持私聊
  • 支持心跳检测
  • 同样非常适合游戏后台开发

linux环境安装启动

首先:参考手册检查/安装workerman环境

1、下载workerman-chat,并解压缩到任意目录

2、启动workermanphp start.php start -d如下图。

php聊天室启动示意图3、浏览器访问端口http://ip:55151或者http://域名:55151,例如 http://workerman.net:55151如图:(如果无法访问请检查服务器防火墙)

RabbitMQ+PHP 教程二(Work Queues)

https://segmentfault.com/a/1190000011829380

CentOS7上安装RabbitMQ

https://www.jianshu.com/p/ce725e41edab

开启允许远程访问(非必须)

vim /etc/rabbitmq/rabbitmq.config

[{rabbit,[{loopback_users,[]}]}].

sudo rabbitmq-plugins enable rabbitmq_management

安装消息延迟插件

cd rabbitmq_server-3.6.6/plugins/

wget https://dl.bintray.com/rabbitmq/community-plugins/rabbitmq_delayed_message_exchange-0.0.1.ez

rabbitmq-plugins enable rabbitmq_delayed_message_exchange

放行端口

firewall-cmd –add-port=15672/tcp –permanent

irewall-cmd –add-port=5672/tcp –permanent

环境版本不一致各种报错

 

centos 网卡设置

cd /etc/sysconfig/network-scripts/

vi ifcfg-eno16777736。进行修改网卡文件,不同机器网卡不同

我们需要首先找到ONBOOT=no ,需要修改为ONBOOT=yes然后保存退出。

然后执行命令 service network restart 重启网卡服务

https://segmentfault.com/a/1190000010693696

环境

  • VMware版本号:12.0.0
  • CentOS版本:CentOS 7.3.1611

注意事项

关闭防火墙

centos 6.x 关闭 iptables

$ service iptables stop # 关闭命令:

centos 7.x 关闭firewall

$ systemctl stop firewalld.service # 停止firewall

不想关闭防火墙,就开放15672端口,设置之后可以通过网页方式管理MQ

安装安装iptables防火墙

yum install iptables-services

编辑配置

$ vi /etc/sysconfig/iptables-config

添加配置

iptables -I INPUT -p tcp --dport 5672 -j ACCEPT
iptables -I INPUT -p tcp --dport 15672 -j ACCEPT

保存配置

$ service iptables save

重启

systemctl restart iptables.service

设置开机自启动

systemctl enable iptables.service

CentOS7.3 安装 iptables 与详细使用

安装

安装 Erlang

RabbitMQ 安装需要依赖 Erlang 环境

$ cd /opt
$ wget http://www.rabbitmq.com/releases/erlang/erlang-19.0.4-1.el7.centos.x86_64.rpm

$ yum install erlang-19.0.4-1.el7.centos.x86_64.rpm

安装 RabbitMQ

$ cd /opt
$ wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.10/rabbitmq-server-3.6.10-1.el7.noarch.rpm
$ yum install rabbitmq-server-3.6.10-1.el7.noarch.rpm

启动服务

$ service rabbitmq-server start

服务状态

$ service rabbitmq-server status
# service rabbitmq-server status
Redirecting to /bin/systemctl status  rabbitmq-server.service
 rabbitmq-server.service - RabbitMQ broker
   Loaded: loaded (/usr/lib/systemd/system/rabbitmq-server.service; disabled; vendor preset: disabled)
   Active: active (running) since Wed 2017-08-16 11:43:33 CST; 8s ago
 Main PID: 17919 (beam)
   Status: "Initialized"
   CGroup: /system.slice/rabbitmq-server.service
           ├─17919 /usr/lib64/erlang/erts-8.0.3/bin/beam -W w -A 64 -P 1048576 -t 5000000 -stbt db -zdbbl 32000 -K true -- -root /usr/lib64/erlang -progname erl -- -home /var/lib/rabbitmq -- -pa /us...
           ├─18062 /usr/lib64/erlang/erts-8.0.3/bin/epmd -daemon
           ├─18160 erl_child_setup 1024
           ├─18165 inet_gethost 4
           └─18166 inet_gethost 4

Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: RabbitMQ 3.6.10. Copyright (C) 2007-2017 Pivotal Software, Inc.
Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: ##  ##      Licensed under the MPL.  See http://www.rabbitmq.com/
Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: ##  ##
Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: ##########  Logs: /var/log/rabbitmq/rabbit@localhost.log
Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: ######  ##        /var/log/rabbitmq/rabbit@localhost-sasl.log
Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: ##########
Aug 16 11:43:32 localhost.localdomain rabbitmq-server[17919]: Starting broker...
Aug 16 11:43:33 localhost.localdomain rabbitmq-server[17919]: systemd unit for activation check: "rabbitmq-server.service"
Aug 16 11:43:33 localhost.localdomain systemd[1]: Started RabbitMQ broker.
Aug 16 11:43:33 localhost.localdomain rabbitmq-server[17919]: completed with 0 plugins.

查看日志

$ less /var/log/rabbitmq/rabbit@localhost.log
=INFO REPORT==== 16-Aug-2017::11:43:32 ===
Starting RabbitMQ 3.6.10 on Erlang 19.0.4
Copyright (C) 2007-2017 Pivotal Software, Inc.
Licensed under the MPL.  See http://www.rabbitmq.com/

=INFO REPORT==== 16-Aug-2017::11:43:32 ===
node           : rabbit@localhost
home dir       : /var/lib/rabbitmq
config file(s) : /etc/rabbitmq/rabbitmq.config (not found)
cookie hash    : kuUba2xGLitNNO48qE0Hrg==
log            : /var/log/rabbitmq/rabbit@localhost.log
sasl log       : /var/log/rabbitmq/rabbit@localhost-sasl.log
database dir   : /var/lib/rabbitmq/mnesia/rabbit@localhost

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Memory limit set to 390MB of 976MB total.

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Enabling free disk space monitoring

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Disk free limit set to 50MB

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Limiting to approx 924 file handles (829 sockets)

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
FHC read buffering:  OFF
FHC write buffering: ON

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Database directory at /var/lib/rabbitmq/mnesia/rabbit@localhost is empty. Initialising from scratch...

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Waiting for Mnesia tables for 30000 ms, 9 retries left

=INFO REPORT==== 16-Aug-2017::11:43:33 ===
Waiting for Mnesia tables for 30000 ms, 9 retries left

这里显示的是没有找到配置文件,我们可以自己创建这个文件

config file(s) : /etc/rabbitmq/rabbitmq.config (not found)

创建rabbitmq.config

$ cd /etc/rabbitmq/
$ vi rabbitmq.config

编辑内容如下:

[{rabbit, [{loopback_users, []}]}].
  • 这里的意思是开放使用,rabbitmq默认创建的用户guest,密码也是guest,这个用户默认只能是本机访问,localhost或者127.0.0.1,从外部访问需要添加上面的配置。

保存配置后重启服务

$ service rabbitmq-server restart

开启管理UI

$ /sbin/rabbitmq-plugins enable rabbitmq_management

重启服务

$ service rabbitmq-server restart

访问管理UI

通过 http://ip:15672 使用guest,guest 进行登陆了

如果不能访问,请检查防火墙
图片描述

授权操作

添加用户

处于安全的考虑,guest这个默认的用户只能通过http://localhost:15672 来登录,其他的IP无法直接使用这个账号。 这对于服务器上没有安装桌面的情况是无法管理维护的,除非通过在前面添加一层代理向外提供服务,这个又有些麻烦了,这里通过配置文件来实现这个功能

命令格式

rabbitmqctl add_user <username> <newpassword>
$ rabbitmqctl add_user ymq 123456
Creating user "ymq"

删除用户

命令格式

rabbitmqctl delete_user <username>
$ rabbitmqctl  delete_user penglei
Deleting user "penglei"

修改密码

命令格式

rabbitmqctl change_password <username> <newpassword>
$ rabbitmqctl  change_password  ymq 123456
Changing password for user "ymq"

用户授权

命令格式

rabbitmqctl set_permissions [-pvhostpath] {user} {conf} {write} {read}

该命令使用户ymq /(可以访问虚拟主机) 中所有资源的配置、写、读权限以便管理其中的资源

$ rabbitmqctl set_permissions -p "/" ymq ".*" ".*" ".*"
Setting permissions for user "ymq" in vhost "/"

查看用户授权

命令格式

rabbitmqctl list_permissions [-p VHostPath]
$ rabbitmqctl list_permissions -p /
Listing permissions in vhost "/"
guest    .*    .*    .*
ymq    .*    .*    .*

查看当前用户列表

可以看到添加用户成功了,但不是administrator角色

$ rabbitmqctl list_users
Listing users
guest    [administrator]
ymq    []

添加角色

这里我们也将ymq用户设置为administrator角色

命令格式

rabbitmqctl set_user_tags <username> <tag>
$ rabbitmqctl set_user_tags ymq administrator
Setting tags for user "ymq" to [administrator]

再次查看权限

$ rabbitmqctl list_users
Listing users
guest    [administrator]
ymq    [administrator]

清除权限信息

命令格式

rabbitmqctl clear_permissions [-p VHostPath] ymq
rabbitmqctl  clear_permissions  -p /  ymq
Clearing permissions for user "ymq" in vhost "/"

官方文档

后台操作

登录新用户

可以看到 ymq 和 guest 的权限 一样
图片描述

添加用户

鼠标点击,划红线的角色,选择一种
图片描述

设置权限

该用户无权访问任何虚拟主机
图片描述

点击 Set permission

  • 设置可以访问虚拟主机 中所有资源的配置、写、读权限以便管理其中的资源

图片描述

推荐阅读

CentOs7.3 搭建 RabbitMQ 3.6 Cluster 集群服务

Contact

  • 作者:鹏磊
  • 出处:http://www.ymq.io
  • Email:admin@souyunku.com
  • 版权归作者所有,转载请注明出处
  • Wechat:关注公众号,搜云库,专注于开发技术的研究与知识分享

linux go 环境

1、下载地址(自备梯子):https://golang.org/dl/

2、解压 到指定目录 tar -C /usr/local -zxf go1.12.1.linux-amd64.tar.gz

3、声明 root 用户登录。
$ vim /etc/profile
打开/etc/profile后//最后一行插入
export GOROOT=/usr/local/go //这里我的go解压后是在/user/local/go
export GOPATH=~/golib:~/goproject
export GOBIN=~/gobin
export PATH=$PATH:$GOROOT/bin:$GOBIN

/然后 按ESC键 跳到命令模式,然后保存退出
:wq //再按确认键盘
//输入下面才会命令生效
$ source /etc/profile //ok

4、go version

go version go1.12.1 linux/amd64

 

 

 

讲解C栈和PHP递归调用push和pop stack的过程。

https://biglive.xueersi.com/LivePlayBack/index/2-2480-93250

讲解C栈和PHP递归调用push和pop stack的过程。

这个视频内容可以和 Swoole4 协程结合着看。很透彻地把 Swoole4 的实现原理讲明白了。普通的 PHP 程序就是一个 C栈、一个 PHP的栈。而 Swoole4 的协程,变成多个 C栈和PHP栈,可以在不同的栈之间切换,这就是协程的本质。然后底层又使用 Epoll 去做事件驱动,去实现协程调度。

粘包问题

网络协议为计算机网络中进行交互而建立的规则,标准或约定的集合

socket 通讯

socket屏蔽了底层通讯的机制

为了数据高效传输

协议分层

tcp/ip 协议族是一个四层协议系统,自底而上分别是数据链路层,网络层、传输层和应用层

应用层  ping  telnet OSPF DNS

要有应答,

收发有缓冲区

3.1什么是 TCP 粘包?

TCP 粘包是指发送方发送的若干包数据 到 接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。

TCP通信特点

  1. TCP 是流式协议没有消息边界,客户端向服务器端发送一次数据,可能会被服务器端分成多次收到。客户端向服务器端发送多条数据。服务器端可能一次全部收到。

2.保证传输的可靠性,顺序。

3.TCP拥有拥塞控制,所以数据包可能会延后发送。

 

没有消息边界:

可以理解为水在一个水管里的流动,我们不知道哪段数据是一个我们需要的完整数据

 

收发有缓冲区:

比如:当水从一端流到了另一端,我们在收数据的时候,不可能每来一滴水就处理一次,这个缓冲区就相当于有了一个水桶,再接了一定的水之后内核再给数据交到用户空间,

3.3 Swoole怎么处理粘包

3.3.1、EOF 结束协议

通过约定结束符,来确定包数据是否发送完毕

开启open_eof_check=true,并用package_eof来设置一个完整数据结尾字符,同时设置自动拆分open_eof_split

 

注意:

  • 要保证业务数据里不能出现package_eof设置的字符,否则将导致数据错误了。

2、可以手动拆包,去掉open_eof_split,自行 explode(“\r\n”, $data),然后循环发送

3.3.2 固定包头+包体协议

这种方式也非常常见,原理是通过约定数据流的前几个字节来表示一个完整的数据有多长,从第一个数据到达之后,先通过读取固定的几个字节,解出数据包的长度,然后按这个长度继续取出后面的数据,依次循环。

 

案例:

 

 

相关配置:

open_length_check:打开包长检测特性

package_length_type:长度字段的类型,固定包头中用一个4字节或2字节表示包体长度。

package_length_offset:从第几个字节开始是长度,比如包头长度为120字节,第10个字节为长度值,这里填入9(从0开始计数)

package_body_offset:从第几个字节开始计算长度,比如包头为长度为120字节,第10个字节为长度值,包体长度为1000。如果长度包含包头,这里填入0,如果不包含包头,这里填入120

package_max_length:最大允许的包长度。因为在一个请求包完整接收前,需要将所有数据保存在内存中,所以需要做保护。避免内存占用过大。

package_length_type 长度值的类型

长度值的类型,接受一个字符参数,与php的pack函数一致。目前swoole支持10种类型:

c:有符号、1字节

C:无符号、1字节

s:有符号、主机字节序、2字节

S:无符号、主机字节序、2字节

n:无符号、网络字节序、2字节 (常用)

N:无符号、网络字节序、4字节 (常用)

l:有符号、主机字节序、4字节(小写L)

L:无符号、主机字节序、4字节(大写L)

v:无符号、小端字节序、2字节

V:无符号、小端字节序、4字节

服务端A既是客户端也是服务器,服务端A要发送请求到服务端B,然后服务端B返回消息给服务端A

 

 

udb 服务

<?php
/**
 * Created by PhpStorm.
 * User: zhangheg
 * Date: 2019/3/23
 * Time: 14:52
 */

$client = new Swoole\Client(SWOOLE_SOCK_UDP);
$client->sendto('127.0.0.1',9501,'客户端udp来了');
<?php
/**
 * Created by PhpStorm.
 * User: zhangheg
 * Date: 2019/3/23
 * Time: 17:45
 */
//创建Server对象,监听 0.0.0.0:9501端口
$serv = new swoole_server("0.0.0.0", 9501,SWOOLE_PROCESS,SWOOLE_SOCK_UDP);

$serv->set([
    'worker_num' => 1, //设置进程
    'heartbeat_check_interval'=>3, //心跳间隔时间
    'heartbeat_idle_time' => 15, //允许空闲时间 心跳的两倍,容错,允许一次丢包
]);


$serv->on('packet',function ($server,$data,$clientInfo){
    var_dump($data);
    var_dump($clientInfo);
    //$server->sendTo();
});
$serv->start();
class A{


    public function connect($serv, $fd){
        var_dump('classa连接');
        echo "有新的客户端连接,连接标识为$fd" . PHP_EOL;
    }
}