Swoole TCP服务端与客户端的 初步研究 持续更新
简单TCP 服务端实现
server.php
<?php
$serv = new swoole_server('0.0.0.0', 9906);
$serv->set([
'worker_num' => 4, // 最大连接
'max_request' => 10000, // worker进程数
'log_level' => SWOOLE_LOG_ERROR, // 日志等级 关闭开启debug
'trace_flags' => SWOOLE_TRACE_SERVER, // 日志等级 关闭开启debug
]);
// 客户端链接触发
$serv->on('connect', function ($serv, $fd, $reactorId) {
echo "Client:{$reactorId} - {$fd} - Connect.\n";
});
// 接收函数
$serv->on('receive', function ($serv, $fd, $reactorId, $data) {
// echo 'cli:' . $data . "\n";
// 发送数据到客户端
$serv->send($fd, "server: {$reactorId} - {$fd} - {$data}");
// $serv->close($fd);
});
$serv->on('close', function ($serv, $fd) {
echo "Client: Close.\n";
});
//启动服务器
$serv->start();
如果想看是否真的启动了配置中的最大连接数 可以执行以下命令查看
ps aft | grep server.php
set相关配置参数
名称 | 参数值 | 描述 | 例 |
---|---|---|---|
最大连接 | max_conn |
此参数用来设置Server最大允许维持多少个tcp连接。超过此数量后,新进入的连接将被拒绝。此参数不要调整的过大,根据机器内存的实际情况来设置。底层会根据此数值一次性分配一块大内存来保存Connection信息 |
max_conn => 10000 |
守护进程化 | daemonize |
加入此参数后,执行php server.php将转入后台作为守护进程运行 | daemonize => 1 |
reactor线程数 | reactor_num |
通过此参数来调节Reactor线程的数量,以充分利用多核,reactor_num和默认设置为CPU核数 | reactor_num => 2 |
worker进程数 | worker_num |
设置启动的Worker进程数量。Swoole采用固定Worker进程的模式。全异步非阻塞服务器 worker_num配置为CPU核数的1-4倍即可。同步阻塞服务器,worker_num配置为100或者更高,具体要看每次请求处理的耗时和操作系统负载状况。当设定的Worker进程数小于reactor线程数时,会自动调低reactor线程的数量 |
worker_num => 4 |
max_request | max_request |
此参数表示worker进程在处理完n次请求后结束运行。manager会重新创建一个worker进程。此选项用来防止worker进程内存溢出。PHP代码也可以使用memory_get_usage来检测进程的内存占用情况,发现接近memory_limit时,调用exit()退出进程。manager进程会回收此进程,然后重新启动一个新的Worker进程。onConnect/onClose不增加计数 设置为0表示不自动重启。在Worker进程中需要保存连接信息的服务,需要设置为0. |
max_request => 2000 |
Listen队列长度 | backlog |
此参数将决定最多同时有多少个待accept的连接,swoole本身accept效率是很高的,基本上不会出现大量排队情况。 | backlog => 128 |
CPU亲和设置 | open_cpu_affinity |
启用CPU亲和设置 | open_cpu_affinity => 1 |
TCP_NoDelay启用 | open_tcp_nodelay |
启用tcp_nodelay | open_tcp_nodelay => 1 |
TCP_DEFER_ACCEPT | tcp_defer_accept |
此参数设定一个秒数,当客户端连接连接到服务器时,在约定秒数内并不会触发accept,直到有数据发送,或者超时时才会触发。 | tcp_defer_accept => 5 |
日志文件路径 | log_file |
指定swoole错误日志文件。在swoole运行期发生的异常信息会记录到这个文件中。默认会打印到屏幕。 | log_file => ‘/data/log/swoole.log’ |
数据buffer | open_eof_check package_eof |
buffer主要是用于检测数据是否完整,如果不完整swoole会继续等待新的数据到来。直到收到完整的一个请求,才会一次性发送给worker进程。这时onReceive会收到一个超过SW_BUFFER_SIZE,小于$serv->setting[‘package_max_length’]的数据。目前仅提供了EOF检测、固定包头长度检测2种buffer模式。open_eof_check => true打开buffer package_eof => “\r\n\r\n” 设置EOF | open_eof_check => true package_eof => “\r\n\r\n” |
心跳检测机制 | heartbeat_check_interval heartbeat_idle_time |
heartbeat_check_interval 每隔多少秒检测一次,单位秒,Swoole会轮询所有TCP连接,将超过心跳时间的连接关闭掉。heartbeat_idle_time TCP连接的最大闲置时间,单位s , 如果某fd最后一次发包距离现在的时间超过heartbeat_idle_time会把这个连接关闭。heartbeat_idle_time必须大于或等于heartbeat_check_interval |
heartbeat_check_interval => 30 heartbeat_idle_time => 60 |
worker进程数据包分配模式 | dispatch_mode |
1平均分配,2按FD取模固定分配,3抢占式分配,默认为取模(dispatch=2) | dispatch_mode=>1 |
简单TCP 客户端实现
Client.php
<?php
$client = new swoole_client(SWOOLE_SOCK_TCP); // 同步阻塞
$ret = $client->connect('127.0.0.1', 9906);
if (!$ret) {
exit("Connect Server fail.errCode={$client->errCode}");
}
fwrite(STDOUT, '请输入:');
$msg = trim(fgets(STDIN));
$client->send($msg);
$result = $client->recv();
echo $result;
$client->close();