@phper
2016-12-09T11:04:30.000000Z
字数 2934
阅读 4750
swoole
前面主要讲了tcp得server和client的业务处理,tcp有三次握手,有连接的概览,而UDP服务器与TCP服务器不同,UDP没有连接的概念。启动Server后,客户端无需Connect,直接可以向Server监听的端口发送数据包。server 接受数据的事件为onPacket
, 发送给client的方法变成sendto
。
udp Server
<?php
/**
* Created by PhpStorm.
* User: yangyi
* Date: 2016/12/7
* Time: 18:02
*/
//创建Server对象,监听 127.0.0.1:9503端口,类型为SWOOLE_SOCK_UDP
$serv = new Swoole\Server("127.0.0.1", 9503, SWOOLE_BASE, SWOOLE_SOCK_UDP);
//监听数据发送事件
$serv->on('Packet', function ($serv, $data, $clientInfo) {
//发送给客户端 用sendto
$serv->sendto($clientInfo['address'], $clientInfo['port'], "Server ".$data);
var_dump($data);
});
//启动服务器
$serv->start();
udp client
<?php
/**
* Created by PhpStorm.
* User: yangyi
* Date: 2016/12/7
* Time: 18:02
*/
$client = new Swoole\Client(SWOOLE_SOCK_UDP);
$client->connect('127.0.0.1', 9503, 1);
$i = 0;
while ($i < 1000) {
$client->send($i."\n");
$message = $client->recv();
echo "Get Message From Server:{$message}\n";
$i++;
}
上面server启动之后,会启动一个进程,默认不是4个,就一个主进程,来处理数据。
pstree |grep server.php
| | \--= 87143 yangyi php udp_server.php
然后接受客户端的数据的监听的方法变成了Packet
了,而不是Receive
。发送数据给client 的方法为sendto
。需要客户端的地址和端口。这点和tcp不一样,没有fd
的概念。
$serv->sendto($clientInfo['address'], $clientInfo['port'], "something");
如果业务请求量很大,一个worker 肯定是不够的,我们利用多个task worker的方式来改写下server。
<?php
/**
* Created by PhpStorm.
* User: yangyi
* Date: 2016/12/7
* Time: 18:02
*/
//创建Server对象,监听 127.0.0.1:9503端口,类型为SWOOLE_SOCK_UDP
$serv = new Swoole\Server("127.0.0.1", 9503, SWOOLE_BASE, SWOOLE_SOCK_UDP);
$serv->set([
'worker_num' => 4, # 4个worker
'task_worker_num' => 4, # 4个task
'deamonize' => false,
]);
//监听数据发送事件
$serv->on('Packet', function ($serv, $data, $clientInfo) {
$serv->sendto($clientInfo['address'], $clientInfo['port'], "Server ".$data);
var_dump($clientInfo, $data);
//把任务丢给task
$serv->task($data);
});
$serv->on('Task', function ($serv, $task_id, $from_id, $data) {
echo "This Task {$task_id} from Worker {$from_id}\n";
echo "Data: {$data}\n";
//模拟慢io查询、
for($i = 0 ; $i < 2 ; $i ++ ) {
sleep(1);
echo "Task {$task_id} Handle {$i} times...\n";
}
//return 数据 给 Finish
return "Task {$task_id}'s result";
});
$serv->on('Finish', function ($serv,$task_id, $data) {
echo "Task {$task_id} finish\n";
echo "Result: {$data}\n";
});
//启动服务器
$serv->start();
再看下进程
$ pstree |grep server.php
| | \-+= 88426 501 php udp_server.php #master
| | \-+- 88427 501 php udp_server.php #manager
| | |--- 88428 501 php udp_server.php #worker、task
| | |--- 88429 501 php udp_server.php
| | |--- 88430 501 php udp_server.php
| | |--- 88431 501 php udp_server.php
| | |--- 88432 501 php udp_server.php
| | |--- 88433 501 php udp_server.php
| | |--- 88434 501 php udp_server.php
| | \--- 88435 501 php udp_server.php
发现启动了8个work进程和一个manager进程一个master进程
这样就完成了一个多worker的udp server。
启动server,再启动client。
server
$ php udp_server.php
#打印udp的地址和ip
/Users/yangyi/www/bestPHP/swoole/udp_server.php:22:
array(3) {
'server_socket' =>
int(4)
'address' =>
string(9) "127.0.0.1"
'port' =>
int(55182)
}
#打印客户端发来的数据
/Users/yangyi/www/bestPHP/swoole/udp_server.php:22:
string(2) "0"
#task启动
This Task 0 from Worker 1
Data: 0
Task 0 Handle 0 times...
Task 0 Handle 1 times...
#task finish
Task 0 finish
Result: Task 0's result
client
$ php udp_client.php
#获取server发回的数据
Get Message From Server:Server 0
参考资料: