资讯专栏INFORMATION COLUMN

swoole教程第二节:基础的通讯实现-server篇-1

lemanli / 2744人阅读

摘要:主进程会重新启动一个新的进程来处理任务服务器程序,最大允许的连接数,如此参数用来设置最大允许维持多少个连接。如果没有注册,服务器程序将无法启动。增加是为了防止服务器程序重启,导致复用上一次的消息队列数据,读取到错误的数据守护进程化。

限于本人的技术水准不高,文章中如果有问题的地方希望各位老爷们能够告诉我。
今天说swoole的通讯。
这个swoole的官网首页已经有了例子,TCP Server和TCP Client
官网demo
其实是四个步骤 官网详细介绍

构建Server对象

设置运行时参数

注册事件回调函数

启动服务器

其中 设置运行参数看这里所有的设置参数
为了方便大家看 ,我自己做了整理,看看就好


 2,通过此参数来调节主进程内事件处理线程的数量,以充分利用多核。默认会启用CPU核数相同的数量。
// reactor_num一般设置为CPU核数的1-4倍,在swoole中reactor_num最大不得超过CPU核数*4。
// swoole的reactor线程是可以利用多核,如:机器有128核,那么swoole会启动128线程。每个线程能都会维持一个EventLoop。线程之间是无锁的,
// 指令可以被128核CPU并行执行。考虑到操作系统调度存在一定程度的偏差,可以设置为CPU核数*2,以便最大化利用CPU的每一个核。
$setConfig["reactor_num"]=2;




// 设置启动的worker进程数。
// 业务代码是全异步非阻塞的,这里设置为CPU的1-4倍最合理
// 业务代码为同步阻塞,需要根据请求响应时间和系统负载来调整
// 比如1个请求耗时100ms,要提供1000QPS的处理能力,那必须配置100个进程或更多。
// 但开的进程越多,占用的内存就会大大增加,而且进程间切换的开销就会越来越大。所以这里适当即可。不要配置过大。
// 每个进程占用40M内存,那100个进程就需要占用4G内存
$setConfig["worker_num"]=4;





// 设置worker进程的最大任务数。一个worker进程在处理完超过此数值的任务后将自动退出。这个参数是为了防止PHP进程内存溢出。
// 如果不希望进程自动退出可以设置为0
// 当worker进程内发生致命错误或者人工执行exit时,进程会自动退出。主进程会重新启动一个新的worker进程来处理任务
$setConfig["max_request"]=2000;





// 服务器程序,最大允许的连接数,如max_conn => 10000, 此参数用来设置Server最大允许维持多少个tcp连接。超过此数量后,新进入的连接将被拒绝。
// max_connection最大不得超过操作系统ulimit -n的值,否则会报一条警告信息,并重置为ulimit -n的值
// max_connection默认值为ulimit -n的值
// WARN    swServer_start_check: serv->max_conn is exceed the maximum value[100000].
// 此参数不要调整的过大,根据机器内存的实际情况来设置。Swoole会根据此数值一次性分配一块大内存来保存Connection信息
$setConfig["max_conn"]=10000;











// 配置task进程的数量,配置此参数后将会启用task功能。所以swoole_server务必要注册onTask/onFinish2个事件回调函数。如果没有注册,服务器程序将无法启动。
// task进程是同步阻塞的,配置方式与worker同步模式一致。
// task进程内不能使用swoole_server->task方法
// task进程内不能使用mysql-async/redis-async/swoole_event等异步IO函数
$setConfig["task_worker_num"]=2;








// 设置task进程与worker进程之间通信的方式。
// 1, 使用unix socket通信
// 2, 使用消息队列通信
// 3, 使用消息队列通信,并设置为争抢模式
// 设置为3后,task/taskwait将无法指定目标进程ID
$setConfig["task_ipc_mode"]=3;




// 设置task进程的最大任务数。一个task进程在处理完超过此数值的任务后将自动退出。
// 这个参数是为了防止PHP进程内存溢出。如果不希望进程自动退出可以设置为0。
// task_max_request默认为5000,受swoole_config.h的SW_MAX_REQUEST宏控制
// 1.7.17以上版本默认值调整为0,不会主动退出进程
$setConfig["task_max_request"]=5000;








// 设置task的数据临时目录,在swoole_server中,如果投递的数据超过8192字节,
// 将启用临时文件来保存数据。这里的task_tmpdir就是用来设置临时文件保存的位置。
// 需要swoole-1.7.7+
$setConfig["task_tmpdir"]="/tmp/tasl_tmpdir/";//路径我是随便写的







// 数据包分发策略。可以选择3种类型,默认为2
// 1,轮循模式,收到会轮循分配给每一个worker进程
// 2,固定模式,根据连接的文件描述符分配worker。这样可以保证同一个连接发来的数据只会被同一个worker处理
// 3,抢占模式,主进程会根据Worker的忙闲状态选择投递,只会投递给处于闲置状态的Worker
// 4,IP分配,根据TCP/UDP连接的来源IP进行取模hash,分配给一个固定的worker进程。
// 可以保证同一个来源IP的连接数据总会被分配到同一个worker进程
// 5,UID分配,需要用户代码中调用$serv->bind() 将一个连接绑定1个uid。然后swoole根据UID的值分配到不同的worker进程
// dispatch_mode 4,5两种模式,在 1.7.8以上版本可用
// dispatch_mode=1/3时,底层会屏蔽onConnect/onClose事件,原因是这2种模式下无法保证onConnect/onClose/onReceive的顺序
// 非请求响应式的服务器程序,请不要使用模式1或3
// SWOOLE_BASE模式
// dispatch_mode 配置在BASE模式是无效的,因为BASE不存在投递任务。
// 当reactor收到客户端发来的数据后会立即回调onReceive,不需要投递Worker进程。
$setConfig["dispatch_mode"]=2;










// 设置消息队列的KEY,仅在ipc_mode = 2或task_ipc_mode = 2时使用。
// 设置的Key仅作为队列的基数。此参数的默认值为ftok($php_script_file, 1)。实际使用的消息队列KEY为:
// recv数据消息队列KEY为 message_queue_key
// send数据消息队列KEY为 message_queue_key + 1
// task数据消息队列KEY为 message_queue_key + 2
// recv/send数据队列在server结束后,会自动销毁。
// task队列在server结束后不会销毁,重新启动程序后,task进程仍然会接着处理队列中的任务。
// 1.7.8以前的版本,KEY会+serv->master_pid。增加pid是为了防止服务器程序重启,导致复用上一次的消息队列数据,读取到错误的数据
$setConfig["message_queue_key"]=2;








// 守护进程化。设置daemonize => 1时,程序将转入后台作为守护进程运行。长时间运行的服务器端程序必须启用此项。
// 如果不启用守护进程,当ssh终端退出后,程序将被终止运行。
// 启用守护进程后,标准输入和输出会被重定向到 log_file
// 如果未设置log_file,将重定向到 /dev/null,所有打印屏幕的信息都会被丢弃
$setConfig["daemonize"]=1;





// Listen队列长度,如backlog => 128,此参数将决定最多同时有多少个等待accept的连接。
// 与php-fpm/apache等软件不同,swoole并不依赖backlog来解决连接排队的问题。所以不需要设置太大的backlog参数。
$setConfig["backlog"]= 128;




// log_file => "/data/log/swoole.log", 指定swoole错误日志文件。
// 在swoole运行期发生的异常信息会记录到这个文件中。默认会打印到屏幕。
// 注意log_file不会自动切分文件,所以需要定期清理此文件。
// 观察log_file的输出,可以得到服务器的各类异常信息和警告。
// log_file中的日志仅仅是做运行时错误记录,没有长久存储的必要。
// 开启守护进程模式后(daemonize => true),标准输出将会被重定向到log_file。
// 在PHP代码中echo/var_dump/print等打印到屏幕的内容会写入到log_file文件
$setConfig["log_file"]="/data/log/swoole.log";




// 启用心跳检测,此选项表示每隔多久轮循一次,单位为秒。
// 如 heartbeat_check_interval => 60,表示每60秒,遍历所有连接,如果该连接在60秒内,没有向服务器发送任何数据,此连接将被强制关闭。
// swoole_server并不会主动向客户端发送心跳包,而是被动等待客户端发送心跳。
// 服务器端的heartbeat_check仅仅是检测连接上一次发送数据的时间,如果超过限制,将切断连接。
// heartbeat_check仅支持TCP连接
$setConfig["heartbeat_check_interval"]=60;


// 与heartbeat_check_interval配合使用。表示连接最大允许空闲的时间。如
// array(
// "heartbeat_idle_time" => 600,
// "heartbeat_check_interval" => 60,
// );
// 表示每60秒遍历一次,一个连接如果600秒内未向服务器发送任何数据,此连接将被强制关闭。
$setConfig["heartbeat_idle_time"]=600;





// 打开EOF检测,此选项将检测客户端连接发来的数据,当数据包结尾是指定的字符串时才会投递给Worker进程。
// 否则会一直拼接数据包,直到超过缓存区或者超时才会中止。当出错时swoole底层会认为是恶意连接,丢弃数据并强制关闭连接。
// array(
// "open_eof_check" => true, //打开EOF检测
// "package_eof" => "
", //设置EOF
// )
// 常见的Memcache/SMTP/POP等协议都是以
结束的,就可以使用此配置。
//开启后可以保证Worker进程一次性总是收到一个或者多个完整的数据包。

// EOF检测不会从数据中间查找eof字符串,所以Worker进程可能会同时收到多个数据包,
// 需要在应用层代码中自行explode("
", $data) 来拆分数据包
// 1.7.15版本增加了open_eof_split,支持从数据中查找EOF,并切分数据
$setConfig["open_eof_check"]=1;



// package_eof
// 与open_eof_check配合使用,设置EOF字符串。
// package_eof最大只允许传入8个字节的字符串
$setConfig["package_eof"]="
";






// open_eof_split
// 启用EOF自动分包。当设置open_eof_check后,底层检测数据是否以特定的字符串结尾来进行数据缓冲。
// 但默认只截取收到数据的末尾部分做对比。这时候可能会产生多条数据合并在一个包内。

// 启用open_eof_split参数后,底层会从数据包中间查找EOF,并拆分数据包。
// onReceive每次仅收到一个以EOF字串结尾的数据包。
// open_eof_split在1.7.15以上版本可用
$setConfig["open_eof_split"]=1;



// 打开包长检测特性。包长检测提供了固定包头+包体这种格式协议的解析。
// 启用后,可以保证Worker进程onReceive每次都会收到一个完整的数据包。
$setConfig["open_length_check"]=1;





// s :有符号、主机字节序、2字节短整型
// S:无符号、主机字节序、2字节短整型
// n:无符号、网络字节序、2字节短整型
// N:无符号、网络字节序、4字节整型
// l:有符号、主机字节序、2字节短整型(小写L)
// L:无符号、主机字节序、2字节短整型(大写L)

$setConfig["package_length_type"]="s";




// 设置最大数据包尺寸,开启open_length_check/open_eof_check/open_http_protocol等协议解析后。
// swoole底层会进行数据包拼接。这时在数据包未收取完整时,所有数据都是保存在内存中的。

// 所以需要设定package_max_length,一个数据包最大允许占用的内存尺寸。
// 如果同时有1万个TCP连接在发送数据,每个数据包2M,那么最极限的情况下,就会占用20G的内存空间。

// open_length_check,当发现包长度超过package_max_length,将直接丢弃此数据,并关闭连接,不会占用任何内存。
// open_eof_check,因为无法事先得知数据包长度,所以收到的数据还是会保存到内存中,持续增长。
// 当发现内存占用已超过package_max_length时,将直接丢弃此数据,并关闭连接
// open_http_protocol,GET请求最大允许8K,而且无法修改配置。
// POST请求会检测Content-Length,如果Content-Length超过package_max_length,将直接丢弃此数据,发送http 400错误,并关闭连接
// 此参数不宜设置过大,否则会占用很大的内存
$setConfig["package_max_length"]=2;




// 启用CPU亲和性设置。在多核的硬件平台中,启用此特性会将swoole的reactor线程/worker进程绑定到固定的一个核上。
//可以避免进程/线程的运行时在多个核之间互相切换,提高CPU Cache的命中率。
// 使用taskset命令查看进程的CPU亲和设置:
// taskset -p 进程ID
// pid 24666"s current affinity mask: f
// pid 24901"s current affinity mask: 8
// mask是一个掩码数字,按bit计算每bit对应一个CPU核,如果某一位为0表示绑定此核,进程会被调度到此CPU上,为0表示进程不会被调度到此CPU。
// 示例中pid为24666的进程mask = f 表示未绑定到CPU,操作系统会将此进程调度到任意一个CPU核上。
// pid为24901的进程mask = 8,8转为二进制是 1000,表示此进程绑定在第4个CPU核上。
// 仅推荐在全异步非阻塞的Server程序中启用
$setConfig["open_cpu_affinity"]=1;




// IO密集型程序中,所有网络中断都是用CPU0来处理,如果网络IO很重,CPU0负载过高会导致网络中断无法及时处理,那网络收发包的能力就会下降。
// 如果不设置此选项,swoole将会使用全部CPU核,底层根据reactor_id或worker_id与CPU核数取模来设置CPU绑定。
// 如果内核与网卡有多队列特性,网络中断会分布到多核,可以缓解网络中断的压力
// 此选项必须与open_cpu_affinity同时设置才会生效
// array("cpu_affinity_ignore" => array(0, 1))
// 接受一个数组作为参数,array(0, 1) 表示不使用CPU0,CPU1,专门空出来处理网络中断。
$setConfig["cpu_affinity_ignore"]=array(0, 1);





// open_tcp_nodelay
// 启用open_tcp_nodelay,开启后TCP连接发送数据时会关闭Nagle合并算法,
// 立即发往客户端连接。在某些场景下,如http服务器,可以提升响应速度
$setConfig["open_tcp_nodelay"]=1;





//启用tcp_defer_accept特性,可以设置为一个数值,表示当一个TCP连接有数据发送时才触发accept。
$setConfig["tcp_defer_accept"]=5;




// 设置SSL隧道加密,设置值为一个文件名字符串,制定cert证书和key的路径。
$setConfig["ssl_cert_file"]="/config/ssl.crt";
$setConfig["ssl_key_file"]="/config//ssl.key";




// 设置worker/task子进程的所属用户。服务器如果需要监听1024以下的端口,
// 必须有root权限。但程序运行在root用户下,代码中一旦有漏洞,攻击者就可以以root的方式执行远程指令,风险很大。
// 配置了user项之后,可以让主进程运行在root权限下,子进程运行在普通用户权限下。
// 此配置在swoole-1.7.9以上版本可用
// 仅在使用root用户启动时有效
$setConfig["user"]="apache";
// 设置worker/task子进程的进程用户组。与user配置相同,此配置是修改进程所属用户组,提升服务器程序的安全性。
$setConfig["group"]="www-data";
// 重定向Worker进程的文件系统根目录。此设置可以使进程对文件系统的读写与实际的操作系统文件系统隔离。提升安全性
$setConfig["chroot"]="/data/server/";







// 调整管道通信的内存缓存区长度。swoole的reactor线程与worker进程之间使用unix socket进行通信,
// 在收发大量数据的场景下,需要启用内存缓存队列。此函数可以修改内存缓存的长度。
// 此参数在1.7.17以上版本默认为32M,1.7.17以下版本默认为8M
$setConfig["pipe_buffer_size"]=2;







// 此配置影响swoole 2个方面
// 数据发送缓存区
// 调整连接发送缓存区的大小。TCP通信有拥塞控制机制,服务器向客户端发送大量数据时,并不能立即发出。这时发送的数据会存放在服务器端的内存缓存区内。此参数可以调整内存缓存区的大小。
// 如果发送数据过多,客户端阻塞,数据占满缓存区后Server会报如下错误信息:
// swFactoryProcess_finish: send failed, session#1 output buffer has been overflowed.
// swoole_server->send大小
// 调用 swoole_server->send, swoole_http_server->end/write,swoole_websocket_server->push 时,最大发送的数据不得超过 buffer_output_size 配置。
// buffer_output_size默认为2M,缓存区塞满后send将会失败
// 注意此函数不应当调整过大,避免拥塞的数据过多,导致吃光机器内存
// 开启大量worker进程时,将会占用worker_num * buffer_output_size 字节的内存
$setConfig["buffer_output_size"]=2;//




// enable_unsafe_event
// swoole在配置dispatch_mode=1或3后,因为系统无法保证onConnect/onReceive/onClose的顺序,默认关闭了onConnect/onClose事件。

// 如果应用程序需要onConnect/onClose事件,并且能接受顺序问题可能带来的安全风险,
//可以通过设置 enable_unsafe_event = true,启用onConnect/onClose事件

// enable_unsafe_event配置在1.7.18以上版本可用

$setConfig["enable_unsafe_event"]=1;




// swoole在配置dispatch_mode=1或3后,系统无法保证onConnect/onReceive/onClose的顺序,因此可能会有一些请求数据在连接关闭后,才能到达Worker进程。
// discard_timeout_request配置默认为true,表示如果worker进程收到了已关闭连接的数据请求,将自动丢弃。
// discard_timeout_request如果设置为false,表示无论连接是否关闭Worker进程都会处理数据请求。
$setConfig["discard_timeout_request"]=1;



配置项目之后该说回调函数了,我也做了一些整理

on("Start", function (swoole_server $server){//仅允许echo、打印Log、修改进程名称。不得执行其他操作。
// 已创建了manager进程
// 已创建了worker子进程
// 已监听所有TCP/UDP端口
// 已监听了定时器
// 接下来要执行
// 主Reactor开始接收事件,客户端可以connect到Server
    echo PHP_EOL;
    echo " start";
    echo PHP_EOL;
    var_dump($server);
    echo PHP_EOL;
});




$serv->on("Shutdown", function (swoole_server $server){
// 在此之前Swoole Server已进行了如下操作
// 已关闭所有线程
// 已关闭所有worker进程
// 已close所有TCP/UDP监听端口
// 已关闭主Rector
// 强制kill进程不会回调onShutdown,如kill -9
// 需要使用kill -15来发送SIGTREM信号到主进程才能按照正常的流程终止
     echo PHP_EOL;
    echo " shutdown";
    var_dump($server);

    echo PHP_EOL;
});




$serv->on("WorkerStart", function (swoole_server $server,  $worker_id){// 不能写 int $worker_id
//此事件在worker进程/task进程启动时发生。这里创建的对象可以在进程生命周期内使用
    echo PHP_EOL;
    echo " WorkerStart";
    echo PHP_EOL;
    var_dump($worker_id);
    echo PHP_EOL;
});




$serv->on("WorkerStop", function (swoole_server $server, int $worker_id){
//此事件在worker进程终止时发生。在此函数中可以回收worker进程申请的各类资源
// $worker_id是一个从0-$worker_num之间的数字,表示这个worker进程的ID
// $worker_id和进程PID没有任何关系
    echo PHP_EOL;
    echo " WorkerStop";
    var_dump($worker_id);
    echo PHP_EOL;
});





//定时器触发
$serv->on("Timer", function (swoole_server $server, int $interval) {
// $interval是定时器时间间隔,根据$interval的值来区分是哪个定时器触发的。这里的定时器是由$serv->addtimer来添加的,是固定间隔循环触发的。
// onTimer中执行时间过长,会导致下一次定时延缓触发。如设定1秒的定时器,1秒后会触发onTimer,onTimer函数用时1.5s,那么第二次触发onTimer的时间为第3秒。中间第2秒的定时器会被丢弃
// onTimer回调函数如果要执行一个耗时操作,最好是使用$serv->task投递到task进程池中执行
    echo PHP_EOL;
    echo " Timer";
    var_dump($interval);
    echo PHP_EOL;
});





$serv->on("connect",function (swoole_server $server,  $fd,  $from_id){
// $server是swoole_server对象
// $fd是连接的文件描述符,发送数据/关闭连接时需要此参数
// $from_id来自那个Reactor线程
// $server是swoole_server对象
// $fd是连接的文件描述符,发送数据/关闭连接时需要此参数
// $from_id来自那个Reactor线程
// onConnect/onClose这2个回调发生在worker进程内,而不是主进程。
// UDP协议下只有onReceive事件,没有onConnect/onClose事件
    echo PHP_EOL;
    echo " connect";
    echo PHP_EOL;
    var_dump($fd);
    echo PHP_EOL;
    var_dump($from_id);
    echo PHP_EOL;
});




//接收到数据时回调此函数,发生在worker进程中
$serv->on("Receive",function (swoole_server $server,  $fd,  $from_id,  $data){
// $server,swoole_server对象
// $fd,TCP客户端连接的文件描述符
// $from_id,TCP连接所在的Reactor线程ID
// $data,收到的数据内容,可能是文本或者二进制内容
//详情  http://wiki.swoole.com/wiki/page/50.html
    echo PHP_EOL;
    echo " Receive";
    echo PHP_EOL;
    var_dump($fd);
    echo PHP_EOL;
    var_dump($from_id);
    echo PHP_EOL;
    var_dump($data);
    echo PHP_EOL;
});





//接收到UDP数据包时回调此函数,发生在worker进程中。
$serv->on("Packet",function (swoole_server $server, string $data, array $client_info){
// $server,swoole_server对象
// $data,收到的数据内容,可能是文本或者二进制内容
// $client_info,客户端信息包括address/port/server_socket 3项数据
// 服务器同时监听TCP/UDP端口时,收到TCP协议的数据会回调onReceive,收到UDP数据包回调onPacket
    echo PHP_EOL;
    echo " Packet";
    echo PHP_EOL;
    var_dump($data);
    echo PHP_EOL;
    var_dump($client_info);
    echo PHP_EOL;
});



//TCP客户端连接关闭后,在worker进程中回调此函数
$serv->on("Close",function (swoole_server $server, int $fd, int $from_id){
// $server是swoole_server对象
// $fd是连接的文件描述符
// $from_id来自那个reactor线程
// 注意:这里回调onClose时表示客户端连接已经关闭,所以无需执行$server->close($fd)。代码中执行$serv->close($fd) 会抛出PHP错误告警。
    echo PHP_EOL;
    echo " Close";
    echo PHP_EOL;
    var_dump($fd);
    echo PHP_EOL;
    var_dump($from_id);
    echo PHP_EOL;
});



//在task_worker进程内被调用。worker进程可以使用swoole_server_task函数向task_worker进程投递新的任务
$serv->on("Task",function (swoole_server $serv, int $task_id, int $from_id, string $data){
// $task_id是任务ID,由swoole扩展内自动生成,用于区分不同的任务。
//$task_id和$from_id组合起来才是全局唯一的,不同的worker进程投递的任务ID可能会有相同
// $from_id来自于哪个worker进程
// $data 是任务的内容
// 返回执行结果到worker进程
// 1.7.2以上的版本,在onTask函数中 return字符串,表示将此内容返回给worker进程。
//worker进程中会触发onFinish函数,表示投递的task已完成。
    echo PHP_EOL;
    echo " Task";
    echo PHP_EOL;
    var_dump($task_id);
    echo PHP_EOL;
    var_dump($from_id);
    echo PHP_EOL;
    var_dump($data);
    echo PHP_EOL;
});





//当worker进程投递的任务在task_worker中完成时,task进程会通过swoole_server->finish()方法将任务处理的结果发送给worker进程。
$serv->on("Finish",function (swoole_server $serv, int $task_id, string $data){
// $task_id是任务的ID
// $data是任务处理的结果内容
// task进程的onTask事件中没有调用finish方法或者return结果。worker进程不会触发onFinish
    echo PHP_EOL;
    echo " Finish";
    echo PHP_EOL;
    var_dump($task_id);
    echo PHP_EOL;
    var_dump($data);
    echo PHP_EOL;
});



//当工作进程收到由sendMessage发送的管道消息时会触发onPipeMessage事件。worker/task进程都可能会触发onPipeMessage事件
$serv->on("PipeMessage",function (swoole_server $server, int $from_worker_id, string $message){
    echo PHP_EOL;
    echo " PipeMessage";
    echo PHP_EOL;
    var_dump($from_worker_id);
    echo PHP_EOL;
    var_dump($message);
    echo PHP_EOL;
});



//当worker/task_worker进程发生异常后会在Manager进程内回调此函数
$serv->on("WorkerError",function (swoole_server $serv, int $worker_id, int $worker_pid, int $exit_code){
// $worker_id是异常进程的编号
// $worker_pid是异常进程的ID
// $exit_code退出的状态码,范围是 1 ~255
// 此函数主要用于报警和监控,一旦发现Worker进程异常退出,
// 那么很有可能是遇到了致命错误或者进程CoreDump。通过记录日志或者发送报警的信息来提示开发者进行相应的处理。
    echo PHP_EOL;
    echo " WorkerError";
    echo PHP_EOL;
    var_dump($from_worker_id);
    echo PHP_EOL;
    var_dump($worker_pid);
    echo PHP_EOL;
    var_dump($exit_code);
    echo PHP_EOL;
});





//当管理进程启动时调用它,函数原型:
$serv->on("ManagerStart",function (swoole_server $serv){
// 在这个回调函数中可以修改管理进程的名称。
// 注意manager进程中不能添加定时器
// manager进程中可以调用task功能
    echo PHP_EOL;
    echo " ManagerStart";
    echo PHP_EOL;
});





//当管理进程结束时调用它,函数原型:
$serv->on("ManagerStop",function (swoole_server $serv){
    echo PHP_EOL;
    echo " ManagerStop";
    echo PHP_EOL;
});



呼,终于写完了,我整理这两个文件的目的是方便大家自己测试,官网有文档,我做的只是代码化。

当我把这些全部看一遍之后,我对swoole_server有了大体印象,比如worker,比如task等等。
来,上个图

图片看不到,看这里

http://wiki.swoole.com/wiki/page/2.html



下面开始我最喜欢的环节 ,跑程序

server.php

start时会失败
$serv = new swoole_server( $host,  $port);
$serv->set(array(
     "worker_num" => 3,   //工作进程数量
 ));
include "OnEvent.php";
$serv->start();

client.php

on("connect", function($cli) {
    $cli->send("hello world
");
});
$client->on("receive", function($cli, $data){
    echo "Received: ".$data."
";
});
$client->on("error", function($cli){
    echo "Connect failed
";
});
$client->on("close", function($cli){
    echo "Connection close
";
});
//发起网络连接
$client->connect("127.0.0.1", 9501, 0.5);

我在server.php里引入了OnEvent.php(我写上了所有的回调函数)
我想看看,server做了什么
来,开始

php server.php

运行结果

 start
object(swoole_server)#1 (4) {
  ["connections"]=>
  object(swoole_connection_iterator)#2 (0) {
  }
  ["setting"]=>
  array(5) {
    ["worker_num"]=>
    int(3)
    ["task_worker_num"]=>
    int(0)
    ["pipe_buffer_size"]=>
    int(33554432)
    ["buffer_output_size"]=>
    int(2097152)
    ["max_connection"]=>
    int(65536)
  }
  ["master_pid"]=>
  int(7418)
  ["manager_pid"]=>
  int(7420)
}


 WorkerStart
int(0)


 WorkerStart
int(1)


 ManagerStart

 WorkerStart
int(2)

程序并没有死,上面的是回调函数里面的输出
server先是 执行start,然后按照设置的worker_num的数目创建worker触发WorkerStart的回调,同时创建Manager执行了ManagerStart
我们再看看上面的两个图片,结合server的运行结果,想必会更多一些了解
我觉得两个图画的很好,让我再看一遍。

好的,顺便的,看到了server的属性

object(swoole_server)#1 (4) {
  ["connections"]=>//看这里 http://wiki.swoole.com/wiki/page/427.html
  object(swoole_connection_iterator)#2 (0) {
  }
  ["setting"]=>//看这里  http://wiki.swoole.com/wiki/page/157.html
  array(5) {
    ["worker_num"]=>
    int(3)
    ["task_worker_num"]=>
    int(0)
    ["pipe_buffer_size"]=>
    int(33554432)
    ["buffer_output_size"]=>
    int(2097152)
    ["max_connection"]=>
    int(65536)
  }
  ["master_pid"]=>//看这里   http://wiki.swoole.com/wiki/page/154.html
  int(7418)
  ["manager_pid"]=>//看这里  http://wiki.swoole.com/wiki/page/155.html
  int(7420)
}

因为配置的没写task,并且当前没有客户端连上来,这里还有一些属性没有展示出来
大家详细的看这里 属性列表

好的,让我们运行客户端

php client.php




 connect
int(1) //  这个是 fd

int(0)// 这个是 from_id


 Receive
int(1)//  这个是 fd

int(0)// 这个是 from_id

string(12) "hello world
"// 这个是 data

这里贴出来 server端多出来的内容

补充一下:对一个对象使用get_class_methods可以获得对象的所有方法,今天忘了怎么获取客户端ip地址了,用这个查了一下,是server的connection_info方法

好的,希望大家用多测试测试,观察server的变化,体会swoole的server调用
结合运行结果来看流程图

今天暂时到这里,哪里我说的不对,请大家指正,我也是一个学习中的人

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/21078.html

相关文章

  • 一个简单混合协议通讯列子,物联网和互联网通讯

    摘要:初始化发送消息判断用户是否登录如果没有登录拒绝连接断开清除信息处理协议主要是方法,轮训获取消息。 这个列子主要讨论Tcp,WebSocket和http之间的通讯。长连接和长连接通讯,长连接和短连接通讯。其他协议同理可得 Tcp: 代表硬件设备 WebSocket: 代表客户端 http: 代表网页 本列子是基于one框架 (https://github.com/lizhicha...

    王军 评论0 收藏0
  • php使用swoole应用场景

    摘要:单进程读写性能可达万,不同的进程使用不同的管道通信,可以最大化利用多核。但这任务如果是调用程序接口时,由于网络的延迟,增加的任务大于消费的任务时,内存占用会不断的增加,导致服务器的内存被占满。 应用场景简介 与硬件设备连接通讯(定位设备) IM系统(用于直播页面的聊天通讯) 场景1 - 实时收集定位数据实时输出(例 滴滴司机行驶轨迹) 说明:需要将所有的定位设备实时的接收,将实时的...

    jsliang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<