Swoole:面向生产环境的 PHP 异步网络通信引擎,使 PHP 开发人员可以编写高性能的异步并发 TCP、UDP、Unix Socket、HTTP,WebSocket 服务。
1.安装
1.搭好centos7虚拟机
2.安装php7.2
3.安装swoole
代码语言:javascript复制 git clone https://gitee.com/swoole/swoole.git
cd swoole
phpize
./configure
make && make install
4.配置php
代码语言:javascript复制 cd /etc/php.d
vi swoole.ini
extension=swoole.so
5.服务server
htpp tcp udp websocket
6.定时器 timer
7.协程Coroutine
协程可以理解为纯用户态的线程,其通过协作而不是抢占来进行切换。
相对于进程或者线程,协程所有的操作都可以在用户态完成,创建和切换的消耗更低。
swoole 协程特点,异步高性能,简单。
8.异步任务
在Server程序中如果需要执行很耗时的操作,比如一个聊天服务器发送广播,Web服务器中发送邮件。如果直接去执行这些函数就会阻塞当前进程,导致服务器响应变慢。
Swoole提供了异步任务处理的功能,可以投递一个异步任务到TaskWorker进程池中执行,不影响当前请求的处理速度。
代码语言:javascript复制<?php
/**
* 私聊 群聊
*/
class skyWebSocket{
public $server;
public $groupClients;
public $uidClients;
public $session;
//用户检测
public $timerClients=array();
public function __construct($ip="0.0.0.0",$port="8282"){
$this->server=new swoole_websocket_server($ip, $port);
echo "ws://$ip:$port";
}
public function connect($client){
$this->timerClients[$client]=1;
}
public function send($client_id,$msg){
return $this->server->push($client_id, json_encode($msg));
}
/**绑定用户**/
public function bindUid($client_id,$uid){
$this->uidClients[$uid][$client_id]=$uid;
}
public function unBindUid($client_id,$uid=0){
unset($this->uidClients[$uid][$client_id]);
}
public function clearUid($uid){
unset($this->uidClients[$uid]);
}
/**给用户发送**/
public function sendToUid($uid,$msg){
if(isset($this->uidClients[$uid])){
foreach($this->uidClients[$uid] as $client_id){
//clientid不存在 要做检测 移除$client_id
if(!$this->send($client_id,$msg)){
$this->unBindUid($client_id,$uid);
}
}
}
}
public function isInGroup($gid,$client_id){
if(!isset($this->groupClients[$gid][$client_id])){
return false;
}
return true;
}
public function joinGroup($gid,$client_id){
$this->groupClients[$gid][$client_id]=$client_id;
}
public function unJoinGroup($gid,$client_id){
unset($this->groupClients[$gid][$client_id]);
}
public function clearGroup($gid){
unset($this->groupClients[$gid]);
}
public function sendGroup($gid,$msg){
foreach($this->groupClients[$gid] as $client_id){
if(!$this->send($client_id, $msg)){
$this->unJoinGroup($gid,$client_id);
}
}
}
public function sendToClient($client_id,$msg){
$this->send($client_id, $msg);
}
public function isUidOnline($uid){
if(isset($this->uidClients[$uid])){
foreach($this->uidClients[$uid] as $client_id){
//clientid不存在 要做检测 移除$client_id
if(!$this->send($client_id,$msg)){
$this->unBindUid($client_id,$uid);
}else{
return true;
}
}
}
}
public function run(){
$this->server->start();
}
public function session_set($client_id,$k,$v){
$this->session[$client_id][$k]=$v;
}
public function session_get($client_id,$k){
return $this->session[$client_id][$k];
}
public function session_del($client_id){
unset($this->session[$client_id]);
}
public function clientClose($client_id){
$this->session_del($client_id);
//删除所有加入的群
if(!empty($this->groupClients)){
foreach($this->groupClients as $gid=>$clients){
foreach($clients as $k=>$cid){
if($client_id=$cid){
unset($this->groupClients[$gid][$k]);
}
}
}
}
//删除所有绑定的uid
if(!empty($this->uidClients)){
foreach($this->uidClients as $uid=>$clients){
foreach($clients as $k=>$cid){
if($cid==$client_id){
unset($this->uidClients[$cid][$k]);
}
}
}
}
}
}
$ws= new skyWebSocket();
$ws->server->on('open', function($server, $req) use($ws) {
$ws->connect($req->fd);
echo "connection open: {$req->fd}n";
});
$ws->server->on('message', function($server, $frame) use ($ws) {
$client_id=$frame->fd;
$msg=json_decode($frame->data,true);
echo $frame->data." n";
if(isset($msg["gid"])){
if(!$ws->isInGroup($msg["gid"],$client_id)){
$ws->joinGroup($msg["gid"],$client_id);
}
$ws->sendGroup($msg["gid"],$msg);
}else{
if(isset($msg["wsclient_to"])){
$to_client_id=$msg["wsclient_to"];
$ws->sendToClient($to_client_id,$msg);
}else{
//需要可登录
$ws->sendToClient($client_id,$msg);
}
}
});
$ws->server->on('close', function($server, $fd) {
echo "connection close: {$fd}n";
});
$ws->run();