欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Swoole Server

程序员文章站 2022-06-12 16:54:04
...

注意

事件的定义顺序没有要求.swoole自己会根据情况触发
不支持set_exception_handler,必须使用try/catch方式处理异常
Redis/MySQL创建连接的相关代码可以放到onWorkerStart回调函数中

定时器要定义在事件回调里面,而且swoole不会判断只开启一次

//这个是不好的,这样一个每一个客户端都会启动一个定时器
$ws->on('connect', function($serv,$fd){
    swoole_timer_tick(2000, function ($timer_id)use($fd) {
        echo $fd."tick-2000ms\n";
    });
});

对于swoole语法不好理解的可以按照js的事件进行理解

swoole的功能大多是在事件进行定义的,你没有触发对应的动作就不会执行对应的代码
就像js中的点击事件一样,你只有点击了才会触发

子类可以调用父类的所有方法和属性

    swoole_http_server是swoole_server的子类,内置了Http的支持
    swoole_websocket_server是swoole_http_server的子类,内置了WebSocket的支持
    swoole_redis_server是swoole_server的子类,内置了Redis服务器端协议的支持

进程数量 2 + worker_num

默认使用SWOOLE_PROCESS模式,因此会额外创建Master和Manager两个进程。
在设置worker_num之后,实际会出现2 + worker_num个进程

server只能在cli模式下运行

Swoole提供的绝大的部分模块只能用于cli命令行终端。
目前只有Client同步客户端可以用于php-fpm环境下(php-fpm简单理解为web url请求模式)

使用pstree 进行观察学习

#假如你通过 /usr/local/php72/bin/php /data/machine/public/test.php
#那么你可以通过pstree 进行观察进程,那些数字是进程pid,16752 是16753 父进程同理16755 
pstree -ap | grep test.php 
  |   |       `-php,16752 /data/machine/public/test.php    //master进程
  |   |           |-php,16753 /data/machine/public/test.php  //manager进程
  |   |           |   `-php,16755 /data/machine/public/test.php  //worker进行

swoole文档中的事件且不分大小写

swoole文档中的事件,例如onConnect,在写代码的时候都是这样$serv->on('connect',function);
而不是$serv->on('onConnect',function);
而且on方法里的事件如connect你也可以写成CONNECT,是不分大小写的

server全代码(会一直补充完善)

tcp模式

/**
 * 回调函数中变量解释
 * $fd:当前连接的客户端的唯一标识,服务端可以通过这个给客户端发信息
 *   */

//设置端口和ip,默认tcp连接
$serv = new swoole_server('127.0.0.1', '9999');
//设置配置
$serv->set([
    'worker_num'=>2,//worker进程数

    //异步任务的工作进程数量,可以通过pstree -ap进行观察会看到4个进程**注意定义了这个一定要定义onTask事件和onFinish
    'task_worker_num'=>2,
]);


//新的TCP连接进入时会执行onConnect事件回调
$serv->on('connect', function($serv,$fd){
    echo "客户端{$fd}连接".PHP_EOL;
});

//处理异步任务
$serv->on('task', function ($serv, $task_id, $from_id, $data) {
    echo "task:{$task_id}-{$from_id}接收到一个任务".date('H:i:s').PHP_EOL;
    sleep('10');
    //返回任务执行的结果,这个不是必须的
    $serv->finish("$data -> OK");
});
//处理异步任务的结果
$serv->on('finish', function ($serv, $task_id, $data) {
    echo "finish:处理完一个任务".date('H:i:s').PHP_EOL;
});

//当某个连接向服务器发送数据时会回调onReceive函数
$serv->on('receive',function($serv,$fd,$from_id,$data){
    //投递异步任务给taskWorker,程序立即返回,继续向下执行代码
    $task_id = $serv->task($data);

    //向客户端fd发送信息(string)data
    $serv->send($fd, '服务端已经收到'.PHP_EOL);
});

//监听连接关闭,**注意是主动断开连接
$serv->on('close',function($serv,$fd){
    echo "客户端{$fd}关闭连接";
});

//启动服务器
$serv->start();

udp模式

/**
 * 回调函数中变量解释
 * $clientInfo :连接的客户端信息
 *   */
//进行udp连接
$serv = new swoole_server('127.0.0.1', 9998,SWOOLE_PROCESS,SWOOLE_SOCK_UDP);

//UDP没有连接的概念,就算你写了不会报错,但是也不会触发事件
//$serv->on('connect',function($serv,$fd){});

//监听数据接收事件,data是客户端数据
$serv->on('packet', function ($serv,$data,$clientInfo){
    //udp使用sendto向客户端发送信息(string)$data
    $serv->sendto($clientInfo['address'], $clientInfo['port'],'接收到客户端信息:'.$data);
});

//UDP没有连接的概念,就算你写了不会报错,但是也不会触发事件
/*
$serv->on('close',function($serv,$fd){
    echo "客户端{$fd}关闭连接";
}); */

//启动服务器
$serv->start();

http模式/web模式

$http = new swoole_http_server('127.0.0.1', 9997);

//客户端http请求
$http->on('request', function ($request, $response) {
    echo '客户端request'.PHP_EOL;
    /* var_dump($request->get, $request->post);
    $response->header("Content-Type", "text/html; charset=utf-8");*/
    $response->end("Hello Swoole. ".PHP_EOL);
});

//对于http来说是没有意义的.可以不定义不会报错
$http->on('connect', function($serv,$fd){
    echo "客户端{$fd}连接".PHP_EOL;
});

//就算使用了tcp进行连接也不会触发
/* $http->on('receive',function($serv,$fd,$from_id,$data){
    //向客户端fd发送信息(string)data
    $serv->send($fd, $data);
}); */

//对于http来说是没有意义的.可以不定义不会报错
$http->on('close',function($serv,$fd){
    echo "客户端{$fd}关闭连接".PHP_EOL;
});

$http->start();

websocket模式

/**
 * WebSocket服务器是建立在Http服务器之上的长连接服务器
 * 可以认为swoole_websocket_server在swoole_http_server基础上多加了一些功能
 *
 *  */
$ws = new swoole_websocket_server('0.0.0.0', 9996);

//客户端首先会发送一个Http的请求与服务器进行握手,所以会触发connect,握手成功后会触发onOpen事件
$ws->on('connect', function($serv,$fd){
    swoole_timer_tick(2000, function ($timer_id)use($fd) {
        echo $fd."tick-2000ms\n";
    });
    echo "connect".PHP_EOL;

});

//能接受到http请求,对应端口要对应
$ws->on('request', function ($request, $response) {
    echo "request".PHP_EOL;

});

//就算使用了tcp发送了数据也不会触发,但是不会报错
/* $ws->on('receive',function($serv,$fd,$from_id,$data){
}); */

//监听WebSocket连接打开事件
$ws->on('open', function($ws,$request){
    echo "open".PHP_EOL;
});

//客户发送websocket信息,注意这里说的是websocket的数据,不是http的数据
$ws->on('message',function($ws,$frame){
    echo "message".PHP_EOL;
    //向客户端fd发送数据
    $ws->push($frame->fd, "server: {$frame->data}");
});

//客户端关闭连接
$ws->on('close',function($ws,$fd){
    echo "close".PHP_EOL;
});

//启动服务器
$ws->start();