/**
* Reactor是master中的独立的几个线程, 在该线程中的每一个子线程中都运行着epoll函数的实例.
* Swoole所有对于事件的监听, 都会在这些线程中实现.比如,来自客户端的连接, 本地通信的管道.以及,异步操作的文件.文件描述符.都会注册在这些epoll中
*
* timer基于Reactor线程中的epoll实例的timeout机制,实现的.
* timer进程是基于,epoll实例的Reactor线程来运行的
* 在taskWorker中是没有Reactor线程的, 所以不能调用swoole的异步IO的这些函数.
* 因此taskWorker 中的定时器,是使用的系统的定时器. 依照个人经验,建议不要在task中搞定时器.
* Swoole是使用堆存放timer,提高检索效果.
* tick是支持第三个参数的, 用户的自定义数据.同时ticker的运行和返回值, 是在同一个worker进程中的.
* tick会返回一个指定的timer_id,如果需要,可以使用swoole_timer_clear清除指定的定时器.
*/
/**
*task 传递数据的大小, 当数据小于8K, 会用管道进行传递.
* 当大于8K 的时候, 会先行,写入一个临时文件当中\tmp
* 当接到的实际的任务之后, 会去读取这个文件将, 将数据读取出来.
*task传递对象, 可以通过对象序列化, 来传递一个对象的拷贝. 并非一个对象的引用.比如说,传一个对象,可以修改对象的数据,但是并不会反应到传送前的worker进程当中.
* 因为task进程和worker进程,是连个不同的进程, 不在同一个内存空间.task中对对象的操作, 并不会反应到worker当中
* 数据库连接, 网络连接对象不可传递.
*task的onfinish回调会发回调用task方法的worker进程
*/
/**
* timer基于epoll的timeout机制,实现的.
* timer进程是基于,epoll实例的Reactor线程来运行的
* 在taskWorker中是没有Reactor线程的, 所以不能调用swoole的异步IO的这些函数.
* 因此taskWorker 中的定时器,是使用的系统的定时器.
* Swoole是使用堆存放timer,提高检索效果.
* tick是支持第三个参数的, 用户的自定义数据.同时ticker的运行和返回值, 是在同一个worker进程中的.
* tick会返回一个指定的timer_id,如果需要,可以使用swoole_timer_clear清除指定的定时器.
*/
注解:
Swoole的很多方法, 不仅是一个方法, 同时也是支持回调的用法的.
进直接调用该方法,则使用该方法的特性进行操作如$serv->close($fd)关闭了该连接.
也可以在构造函数中绑定一个回调$this->serv->on('Close', [$this, 'onClose']);
这种用法,像极了call_user_func_arr();
以前KR那边的的Swoole是直接写在一个方法中的所以CLOSE直接这么干:
$serv->on('Close', function($server, $fd) {
#逻辑代码
}
现在的话,我是直接在一个类中单独绑定所有的需要事件,声明好所有的回调.
如下:
# 激活redis
$this->Redis();
# bind Callback
$this->serv->on('WorkerStart', [$this, 'onWorkerStart']);
$this->serv->on('Connect', [$this, 'onConnect']);
$this->serv->on('Receive', [$this, 'onReceive']);
$this->serv->on('Close', [$this, 'onClose']);
$this->serv->on('Task', [$this, 'onTask']);
$this->serv->on('Finish', [$this, 'onFinish']);
$this->serv->start();
代码的话,具体可以参考.socket章节下的Swoole测试代码
以下方法 [有无回调] 代表该方法是否支持事件回调函数的用法.
所谓回调用法如close最具有代表性:
# 关闭操作
bool swoole_server->close(int $fd, bool $reset = false);
为关闭某个$fd的连接,返回bool值.
# 回调操作
TCP客户端连接关闭后,在worker进程中回调此函数。函数原型:
# 在构造函数中绑定该方法
$this->serv->on('Close', [$this, 'onClose']);
# 有客户端关闭的时候,会触发该方法
function onClose(swoole_server $server, int $fd, int $reactorId);
# 连接关闭回调
public function onClose($serv, $fd, $from_id)
{
echo "Client {$fd} close connect\n";
}
此时作为连接关闭会的事件触发方法.
各种方法,暂未标注,是否支持事件回调用法.
以及,常规使用和回调函数的用法.
日后再补吧.可以参考手册以及我的测试代码
# 激活Swoole, 侦听指定IP和端口
$swSwoole = new Swoole\Websocket\Server('IP','PORT')
官方案例:
创建一个异步Server对象。
$serv = new swoole_server(string $host, int $port = 0, int $mode = SWOOLE_PROCESS,int $sock_type = SWOOLE_SOCK_TCP);
$host参数用来指定监听的ip地址,如127.0.0.1,或者外网地址,或者0.0.0.0监听全部地址
IPv4使用 127.0.0.1表示监听本机,0.0.0.0表示监听所有地址
IPv6使用::1表示监听本机,:: (相当于0:0:0:0:0:0:0:0) 表示监听所有地址
$port监听的端口,如9501
如果$sock_type为UnixSocket Stream/Dgram,此参数将被忽略
监听小于1024端口需要root权限
如果此端口被占用server->start时会失败
$mode运行的模式,swoole提供了3种运行模式,默认为SWOOLE_PROCESS多进程模式
$sock_type指定Socket的类型,支持TCP、UDP、TCP6、UDP6、UnixSocket Stream/Dgram 6种
使用$sock_type | SWOOLE_SSL可以启用SSL隧道加密。启用SSL后必须配置ssl_key_file和ssl_cert_file
1.7.11版本增加了对Unix Socket的支持,详细请参见 /wiki/page/16.html
构造函数中的参数与swoole_server::addlistener中是完全相同的
监听端口失败,在1.9.16以上版本会抛出异常,可以使用try/catch捕获异常,在1.9.16以下版本抛出致命错误
高负载的服务器,请务必调整Linux内核参数
3种Server运行模式介绍
注册Server的事件回调函数。
bool swoole_server->on(string $event, mixed $callback);
第1个参数是回调的名称, 大小写不敏感,具体内容参考回调函数列表,事件名称字符串不要加on
第2个函数是回调的PHP函数,可以是函数名的字符串,类静态方法,对象方法数组,匿名函数。
重复调用on方法时会覆盖上一次的设定
如例:
$serv = new swoole_server("127.0.0.1", 9501);
$serv->on('connect', function ($serv, $fd){
echo "Client:Connect.\n";
});
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
$serv->send($fd, 'Swoole: '.$data);
$serv->close($fd);
});
$serv->on('close', function ($serv, $fd) {
echo "Client: Close.\n";
});
$serv->start();
我的例子:
/**
* socket constructor.
* @author liuhao <lh@btctrade.com>
* 在构造函数中声明所有需要使用的回调函数
* 同时也要给这些回调函数准备一些函数
*/
public function __construct()
{
$this->serv = new swoole_server("127.0.0.1", 9999);
$this->serv->set([
'worker_num' => 2,
'daemonize' => false,
'max_request' => 100000,
'dispath_mode' => 2,
'debug_mode' => 1,
'task_worker_num' => 2,
]);
# bind Callback
$this->serv->on('WorkerStart', [$this, 'onWorkerStart']);
$this->serv->on('Connect', [$this, 'onConnect']);
$this->serv->on('Receive', [$this, 'onReceive']);
$this->serv->on('Close', [$this, 'onClose']);
$this->serv->on('Task', [$this, 'onTask']);
$this->serv->on('Finish', [$this, 'onFinish']);
$this->serv->start();
}
$swSwoole->On('open', function($server, $req){
});
OPEN为, 前端连接swoole成功后的触发的回调.
该连接,表示已握手成功后连接畅通触发.
$swSwoole->On('close', function($server,$req){
});
CLOSE表示连接断开后触发的操作,
该操作属于被动操作, 即:不是用来关闭连接用的.
一般我用来做: 连接断开, 从数据库中删除该用户的连接ID(Swoole连接时分配的, 我将它存在了redis,便于后续的群发推送)
可以直接操作CLOSE来关闭某个连接
swoole_server->close(int $fd, bool $reset = false);
操作成功返回true,失败返回false.
Server主动close连接,也一样会触发onClose事件。
不要在close之后写清理逻辑。应当放置到onClose回调中处理
$reset设置为true会强制关闭连接,丢弃发送队列中的数据
/**
* worker 进程开始时的回调,
* 该回调, 会在task和worker创建之初,进行创建.
* 所以他分不清,task和worker, 也可以理解为, worker和task同时都走这里
* $serv->taskworker 可以用来判断他是数据worker 还是task
* 通过var_dump($worker_id)也可以得知;
*/
$swServer->On('WorkerStart', function ($server, $workerId) use($redis){
}
今天在使用该方法进行,
多进程处理时,遇到了一个问题:
在On WorkerStart 下直接使用$redis->sMembers()获取无序集合内的所有信息时
,发生错误但是能用, 提示:
ERROR zm_deactivate_swoole (ERROR 503): Fatal error: Uncaught RedisException: read error on connection
如果在WorkerStart 的中使用原生的PHP链接redis方式, 是没有问题的. 但是使用封装好的redis单例类, 则报错....
要命的时, 我原来以为,redis未使用pconnect连接的原因,事实证明不是这个原因.
随后我将$redis->sMembers();放在多进程判断if(进程=XX)里面的定时器中,
该问题,解决, 郁闷.
具体是为什么? 我不太清楚, 查了下手册, 然而手册并不完善.
我认为是:
On worker方法, 是worker进程开始后的回调.
而worker进程开始是多个的.
遇到一个逻辑问题, 是虽然使用原生的PHP链接redis, 解决的在ON WorkerStart中封装的redis类报错问题. 但是, 由于该回调是, Swoole进程开始运行时的回调.
在这里获取到的用户链接Swoole的socket继承ID是不准确的, 进程开始时获取的时进程还未运行时的数据,
所以, 后来我又将redis->sMembers();放在了定时器中.不间断获取.
以及在,ON open,及用户成功连接时,即刻推送一次.
swoole_server->connection_info函数用来获取连接的信息,别名是swoole_server->getClientInfo
function swoole_server->connection_info(int $fd, int $extraData, bool $ignoreError = false)
如果传入的fd存在,将会返回一个数组
连接不存在或已关闭,返回false
第3个参数表示是否忽略错误,如果设置为true,即使连接关闭也会返回连接的信息
实例:
$serv->connection_info($fd);
$fdinfo = $serv->connection_info($fd);
var_dump($fdinfo);
array(5) {
["reactor_id"]=>
int(3)
["server_fd"]=>
int(14)
["server_port"]=>
int(9501)
["remote_port"]=>
int(19889)
["remote_ip"]=>
string(9) "127.0.0.1"
["connect_time"]=>
int(1390212495)
["last_time"]=>
int(1390212760)
}
$udp_client = $serv->connection_info($fd, $from_id);
var_dump($udp_client);
reactor_id 来自哪个reactor线程
server_fd 来自哪个server socket 这里不是客户端连接的fd
server_port 来自哪个Server端口
remote_port 客户端连接的端口
remote_ip 客户端连接的ip
connect_time 连接到Server的时间,单位秒
last_time 最后一次发送数据的时间,单位秒
close_errno 连接关闭的错误码,如果连接异常关闭,close_errno的值是非零,可以参考Linux错误信息列表
websocket_status [可选项] WebSocket连接状态,当服务器是Swoole\WebSocket\Server时会额外增加此项信息
uid [可选项] 使用bind绑定了用户ID时会额外增加此项信息
ssl_client_cert [可选项] 使用SSL隧道加密,并且客户端设置了证书时会额外添加此项信息
一般我的使用方式是, 在连接的时候即onConnect()中使用该函数,获取客户端信息,存储起来.用作统计.
得到当前Server的活动TCP连接数,启动时间,accpet/close的总次数等信息。
array swoole_server->stats();
返回的结果数组示例:
array (
'start_time' => 1409831644,
'connection_num' => 1,
'accept_count' => 1,
'close_count' => 0,
'task_queue_num' => 10,
'task_queue_bytes' => 65536,
);
start_time 服务器启动的时间
connection_num 当前连接的数量
accept_count 接受了多少个连接
close_count 关闭的连接数量
tasking_num 当前正在排队的任务数
task_queue_num 消息队列中的Task数量
task_queue_bytes 消息队列的内存占用字节数
一般我的用法是在连接时,$serv->stats()使用该函数,判断一下服务器状态,是否允许连接.
用来遍历当前Server所有的客户端连接,connection_list方法是基于共享内存的,不存在IOWait,遍历的速度很快。另外connection_list会返回所有TCP连接,而不仅仅是当前worker进程的TCP连接。
我认为需要切记的是:
该函数, 会返回所有的TCP连接,而不仅仅是当前worker进程的TCP连接.
实例:
# 分批次发送, 官方实例
$start_fd = 0;
while(true)
{
# connection_list函数获取现在连接中的fd
$conn_list = $ws->connection_list($start_fd, 100); # 获取从fd之后一百个进行发送
var_dump($conn_list);
echo count($conn_list);
if($conn_list === false || count($conn_list) === 0)
{
echo "finish\n";
return;
}
$start_fd = end($conn_list);
foreach($conn_list as $fd)
{
$ws->push($fd, $msg);
}
}
# 我的实例
# 推送所有在线的客户端
$start_fd = 0;
while (true) {
# 获取所有在线的客户端连接
$conn_list = $serv->connection_list($start_fd, 100);
if (isset($conn_list) && !empty($conn_list)) {
foreach ($conn_list as $v1) {
# 不向自身, 返回消息
if ($v1 == $data['fd']) continue;
# 该连接处于有效状态
if ($serv->exist($v1)) {
# 发送消息
$serv->send($v1, '这里是全局推送信息,你是第: ' . $v1 . '连接的客户端' . '处理你的task为:' . $task_id);
}
}
} else {
break;
}
}
/**
*task 传递数据的大小, 当数据小于8K, 会用管道进行传递.
* 当大于8K 的时候, 会先行,写入一个临时文件当中\tmp
* 当接到的实际的任务之后, 会去读取这个文件将, 将数据读取出来.
*task传递对象, 可以通过对象序列化, 来传递一个对象的拷贝. 并非一个对象的引用.比如说,传一个对象,可以修改对象传过来的数据在本进程中使用,但是并不会反应到传送前的worker进程当中.
* 因为task进程和worker进程,是连个不同的进程, 不在同一个内存空间.task中对对象的操作, 并不会反应到worker当中
* 数据库连接, 网络连接对象不可传递.
*task的onfinish回调会发回调用task方法的worker进程
*/
使用Task功能,必须先设置 task_worker_num,并且必须设置Server的onTask和onFinish事件回调函数。
int swoole_server::task(mixed $data, int $dst_worker_id = -1)
$data要投递的任务数据,可以为除资源类型之外的任意PHP变量
$dst_worker_id可以制定要给投递给哪个task进程,传入ID即可,范围是0 - (serv->task_worker_num -1)
调用成功,返回值为整数$task_id,表示此任务的ID。如果有finish回应,onFinish回调中会携带$task_id参数
调用失败,返回值为false
未指定目标Task进程,调用task方法会判断Task进程的忙闲状态,底层只会向处于空闲状态的Task进程投递任务。如果所有Task进程均处于忙的状态,底层会轮询投递任务到各个进程。可以使用 server->stats 方法获取当前正在排队的任务数量。
1.8.6版本增加了第三个参数,可以直接设置onFinish函数,如果任务设置了回调函数,Task返回结果时会直接执行指定的回调函数,不再执行Server的onFinish回调
需要注意的是:
swoole_server->task/taskwait/finish 3个方法当传入的$data数据超过8K时会启用临时文件来保存。当临时文件内容超过 server->package_max_length 时底层会抛出一个警告。此警告不影响数据的投递,过大的Task可能会存在性能问题。
task底层使用Unix Socket管道通信,是全内存的,没有IO消耗。单进程读写性能可达100万/s,不同的进程使用不同的管道通信,可以最大化利用多核。
该方法是异步回调的.
一般我的用法是, 在swoole_server中的onReceive或者swoole_websocket_server中的onMessage.
中即,接受到用户的请求后调用task进程进行异步处理.$serv->task($data);
然后在ontask进程中进行数据库操作或者,广播消息.
如例:
# 接收数据回调
public function onReceive(swoole_server $serv, $fd, $from_id, $data)
{
echo "Get Message From Client {$fd}: {$data}\n";
# 组建需要异步的数据
$data = [
'task' => 'task_1', # 该任务命名为task_1,方便后边测试
'params' => $data, # 传递的参数
'fd' => $fd # 客户端的描述符
];
$serv->task(json_encode($data));
}
# 异步回调
public function onTask($serv, $task_id, $from_id, $data)
{
echo "This task {$task_id} from Worker {$from_id}\n";
echo "Data: {$data}\n";
var_dump($data);
# 转换接收到的JSON数据
$data = json_decode($data, true);
# 数据接收到的数据
echo "Receive Task : {$data['task']}\n";
# 返回用户数据
$serv->send($data['fd'], $data['params']);
return "Finished";
}
# 异步结束回调(swoole机制, task运行完毕,如果finish回调存在,则返回到onFinish中)
public function onFinish($serv, $task_id, $data)
{
echo "Task {$task_id} finish\n";
echo "Result: {$data}\n";
}
Tash的onfinish方法回调会调用task方法的worker进程,而不是其他worker进程(worker是有多个的).
此函数用于在task进程中通知worker进程,投递的任务已完成。此函数可以传递结果数据给worker进程。
$serv->finish("response");
使用swoole_server::finish函数必须为Server设置onFinish回调函数。此函数只可用于task进程的onTask回调中
finish方法可以连续多次调用,Worker进程会多次触发onFinish事件
在onTask回调函数中调用过finish方法后,return数据依然会触发onFinish事件
swoole_server::finish是可选的。如果worker进程不关心任务执行的结果,不需要调用此函数
在onTask回调函数中return字符串,等同于调用finish
如例子:
# 异步回调
public function onTask($serv, $task_id, $from_id, $data)
{
echo "This task {$task_id} from Worker {$from_id}\n";
echo "Data: {$data}\n";
var_dump($data);
# 转换接收到的JSON数据
$data = json_decode($data, true);
# 数据接收到的数据
echo "Receive Task : {$data['task']}\n";
# 返回用户数据
$serv->send($data['fd'], $data['params']);
# 直接返回这个, 也可调用onFinish方法
return "Finished";
}
# 异步结束回调(swoole机制, task运行完毕,如果finish回调存在,则返回到onFinish中)
public function onFinish($serv, $task_id, $data)
{
echo "Task {$task_id} finish\n";
echo "Result: {$data}\n";
}
两者在用的时候,单纯从用的角度来讲,性质是一样的.
不同的是message是websocket的方法
function onReceive(swoole_server $server, int $fd, int $reactor_id, string $data);
$server,swoole_server对象
$fd,TCP客户端连接的唯一标识符
$reactor_id,TCP连接所在的Reactor线程ID
$data,收到的数据内容,可能是文本或者二进制内容
关于$fd和$reactor_id 详细的解释
未开启swoole的自动协议选项,onReceive回调函数单次收到的数据最大为64K
Swoole支持二进制格式,$data可能是二进制数据
bool swoole_server->send(int $fd, string $data, int $extraData = 0);
$data,发送的数据,TCP协议最大不得超过2M,可修改 buffer_output_size 改变允许发送的最大包长度
UDP协议不得超过65507,UDP包头占8字节, IP包头占20字节,65535-28 = 65507
UDP服务器使用$fd保存客户端IP,$extraData保存server_fd和port
发送成功会返回true
发送失败会返回false,调用$server->getLastError()方法可以得到失败的错误码
如例子:
# 异步回调
public function onTask($serv, $task_id, $from_id, $data)
{
echo "This task {$task_id} from Worker {$from_id}\n";
echo "Data: {$data}\n";
$data = json_decode($data, true);
# 向该客户端发送数据
$serv->send($data['fd'], '定时器10秒后发送的测试消息' . time());
return 'Finished';
}
- 关于timer定时器的ticker和after [有回调]
int swoole_timer_tick(int $ms, callable $callback, mixed $user_param);
tick定时器,可以自定义回调函数
worker进程结束运行后,所有定时器都会自动销毁
tick/after定时器不能在swoole_server->start之前使用
用法案例:
# 在workerStart中,直接用,以及单独声明一个回调.
# 同时worker中激活了一个test对象, 而后在ticker的回调中调用得到.
# 说明两者的变量时可以通用的, 在同一作用域.
/**
* worker 进程开始时的回调,
* 该回调, 会在task和worker创建之初,进行创建.
* 所以他分不清,task和worker, 也可以理解为, worker和task同时都走这里
* $serv->taskworker 可以用来判断他是数据worker 还是task
* 通过var_dump($worker_id)也可以得知;
*/
public function onWorkerStart($serv, $worker_id)
{
echo "onWorkerStart: {$worker_id} \n";
# 指定某一个worker才运行
if ($worker_id == 1) {
# 定时器,写法1
/* swoole_timer_tick(1000, function ($timer_id, $params) {
echo "Timer Tick Params: {$params}\n" . time() . PHP_EOL;
}, 'hello world');*/
# 定时器,写法2,利用单独的回调,用于测试,ticker和worker的变量能否通用.
$this->test = new Test();
$this->test->index = 100;
$serv->tick(1000, [$this, 'onTicker'], 'Hello Ticker');
}
}
# ticker定时器的回调
public function onTicker($timer_id, $params = '')
{
echo "This is Ticker Timer {$timer_id}\n";
# 正常输入, 在OnworkerStart中赋值的对象
var_dump($this->test->index);
}
# 官方案例
在onReceive中使用
function onReceive($server, $fd, $from_id, $data) {
$server->tick(1000, function() use ($server, $fd) {
$server->send($fd, "hello world");
});
}
在onWorkerStart中使用, 而onWorkerStart启动的时候,
是同时启动的worker和task所以此处需要特别处理.
低于1.8.0版本task进程不能使用tick/after定时器,所以需要使用$serv->taskworker进行判断
task进程可以使用addtimer间隔定时器
function onWorkerStart(swoole_server $serv, $worker_id)
{
if (!$serv->taskworker) {
$serv->tick(1000, function ($id) {
var_dump($id);
});
}
else
{
$serv->addtimer(1000);
}
}
swoole_server->after(int $after_time_ms, mixed $callback_function);
swoole_server::after函数是一个一次性定时器,执行完成后就会销毁
$after_time_ms 指定时间,单位为毫秒
$callback_function 时间到期后所执行的函数,必须是可以调用的。callback函数不接受任何参数
低于1.8.0版本task进程不支持after定时器,仅支持addtimer定时器
$after_time_ms 最大不得超过 86400000
此方法是swoole_timer_after函数的别名
用法和ticker相同,不在详细举例,只举一个简单的例子
# 接收客户端数据的回调
public function onReceive( $serv, $fd, $from_id, $data)
{
echo "Get Message From Client {$fd}: {$data}\n";
# 由此处可知,该回调为worker的回调,并非taskworker
if ($serv->taskworker) {
echo 'This is TaskWorker' . PHP_EOL;
} else {
echo 'This is Worker' . PHP_EOL;
}
# 10秒钟后进行推送
swoole_timer_after(10000, function () use ($serv, $fd) {
$serv->task(json_encode(['fd' => $fd]));
});
}
- 关于exists判断该描述符(fd)的客户端是否在线
bool function swoole_server->exist(int $fd)
检测fd对应的连接是否存在。
$fd对应的TCP连接存在返回true,不存在返回false
此接口是基于共享内存计算,没有任何IO操作
swoole_server->exist在1.7.18以上版本可用
案例:
在全局广播中, 想所有在线客户端推送 时,判断该连接是否正常在线.
# 推送所有在线的客户端
$start_fd = 0;
while (true) {
# 获取所有在线的客户端连接
$conn_list = $serv->connection_list($start_fd, 100);
if (isset($conn_list) && !empty($conn_list)) {
foreach ($conn_list as $v1) {
# 不向自身, 返回消息
if ($v1 == $data['fd']) continue;
# 该连接处于有效状态
if ($serv->exist($v1)) {
# 发送消息
$serv->send($v1, '这里是全局推送信息,你是第: ' . $v1 . '连接的客户端' . '处理你的task为:' . $task_id);
}
}
} else {
break;
}
}
function onHandShake(swoole_http_request $request, swoole_http_response $response);
在WebSocket开发中, Swoole是进行自动握手的, 如果想要手动握手, 可以使使用这个.
onHandShake事件回调是可选的
设置onHandShake回调函数后不会再触发onOpen事件,需要应用代码自行处理
onHandShake函数必须返回true表示握手成功,返回其他值表示握手失败
内置的握手协议为Sec-WebSocket-Version: 13,低版本浏览器需要自行实现握手
例如:
$server->on('handshake', function (\swoole_http_request $request, \swoole_http_response $response) {}
通过:
$request->header;
来获取请求头.
$response->header($key, $val);
来设置响应头.
主体思想,即为, $request获取请求头, 得到key,处理后$response响应.
具体操作可查看官方操作.
swoole_server::set()函数所设置的参数会保存到swoole_server::$setting属性上。在回调函数中可以访问运行参数的值。
在swoole-1.6.11+可用
官方案例:
$serv = new swoole_server('127.0.0.1', 9501);
$serv->set(array('worker_num' => 4));
echo $serv->setting['worker_num'];
得到当前Worker进程的编号,包括Task进程。
int $server->worker_id;
这个属性与onWorkerStart时的$worker_id是相同的。
Worker进程编号范围是[0, $serv->setting['worker_num'])
task进程编号范围是[$serv->setting['worker_num'], $serv->setting['worker_num'] + $serv->setting['task_worker_num'])
工作进程重启后worker_id的值是不变的
布尔类型
true表示当前的进程是Task工作进程
false表示当前的进程是Worker进程
此属性在swoole-1.7.15以上版本可用
TCP连接迭代器,可以使用foreach遍历服务器当前所有的连接,此属性的功能与swoole_server->connnection_list是一致的,但是更加友好。遍历的元素为单个连接的fd。
注意$connections属性是一个迭代器对象,不是PHP数组,所以不能用var_dump或者数组下标来访问,只能通过foreach进行遍历操作。
foreach($server->connections as $fd)
{
$server->send($fd, "hello");
}
echo "当前服务器共有 ".count($server->connections). " 个连接\n";
此属性在1.7.16以上版本可用
连接迭代器依赖pcre库(不是PHP的pcre扩展),未安装pcre库无法使用此功能
所以一般我都用swoole_server->connections_list();