技术饭
php扩展swoole的基础使用
Swoole:面向生产环境的 PHP 异步网络通信引擎,使 PHP 开发人员可以编写高性能的异步并发 TCP、UDP、Unix Socket、HTTP,WebSocket 服务。Swoole 可以广泛应用于互联网、移动通信、企业软件、云计算、网络游戏、物联网(IOT)、车联网、智能家居等领域。 使用 PHP + Swoole 作为网络通信框架,可以使企业 IT 研发团队的效率大大提升,更加专注于开发创新产品。
基础用法:
1、创建TCP服务器
<?php
//创建TCP服务器
/**
* 创建TCP服务对象 new swoole_server($host, $port, $mode, $sock_type)
* $host : 127.0.0.1 监听本地IP
* 139.196.86.20 监听远程IP
* 0.0.0.0 不限制IP
* $port : 9501 端口号,小于1024需要root权限
* $mode : SWOOLE_PROCESS 多进程的方式
* $sock_type:SWOOLE_SOCK_TCP 默认TCP
*/
//创建对象,监听 127.0.0.1:9501端口
$serv = new swoole_server("0.0.0.0", 9501);
/**
* 使用
* $serv->on($event, $callback)
* $event : 事件
* connect : 当建立连接的时 $serv:服务器信息, $fd:客户端信息
* receive : 当接收数据时 $serv:服务器信息, $fd:客户端信息, $from_id:ID, $data:数据
* close : 关闭连接
*/
//连接
$serv->on('connect', function ($serv, $fd) {
echo "建立连接\n";
});
//接收数据
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
//$serv->send($fd, "接收到数据: " . $data);
echo "接收到数据:\n";
var_dump($data);
});
//监听连接关闭事件
$serv->on('close', function ($serv, $fd) {
echo "关闭连接\n";
});
//开启服务
$serv->start();
?>
2、创建UDP服务器
<?php
//创建UDP服务器
//创建UDP对象,监听 127.0.0.1:9501端口,类型为SWOOLE_SOCK_UDP
$serv = new swoole_server("0.0.0.0", 9501, SWOOLE_PROCESS, SWOOLE_SOCK_UDP);
/**
* 监听数据接收事件 packet
* $serv : 服务器信息
* $data : 数据
* $fd : 客户端信息
*/
$serv->on('packet', function ($serv, $data, $fd) {
$serv->sendto($fd['address'], $fd['port'], "返回数据 " . $data);
var_dump($fd);
});
//启动服务器
$serv->start();
//使用 nc -u 127.0.0.1 9501 做测试
?>
3、创建HTTP服务器
<?php
//创建HTTP服务器
/**
* new swoole_http_server($host, $port) 继承于 swoole_server()
*/
//创建服务
$serv = new swoole_http_server('0.0.0.0', 9501);
/**
* 接收请求
* $request : 请求数据
* $respone : 响应数据
*/
$server->on('request', function ($request, $response) {
var_dump($request);
$response->header('Content-Type', 'text/html;charset=utf-8');
$response->end('返回数据:' . rand(100, 20000));
});
//启动服务
$server->start();
//使用 http://stest.copylian.com:9501/ 直接浏览器范围
?>
4、创建websocket服务器
<?php
//创建websocket服务器
/**
* new swoole_websocket_server($host, $prot) 继承于 swoole_http_server()
*/
//创建websocket服务器对象,监听0.0.0.0:9501端口
$serv = new swoole_websocket_server("0.0.0.0", 9501);
/**
* 监听打开
* $serv : 服务器信息
* $request : 请求信息
*/
$serv->on('open', function ($serv, $request) {
var_dump($request);
$serv->push($request->fd, "我是发送过去的数据!");
});
//消息事件
$serv->on('message', function ($serv, $request) {
//echo "消息: " . $request->data . "\n";
//$serv->push($request->fd, "数据: " . $request->data);
});
//关闭
$serv->on('close', function ($serv, $fd) {
echo "关闭\n";
});
//启动服务
$serv->start();
//使用 js的 new WebSocket(wsServer) 做测试
?>
<script type="text/javascript">
//websocket地址
var wsServer = 'ws://139.196.86.20:9501';
//websocket实例化
var websocket = new WebSocket(wsServer);
//打开
websocket.onopen = function (evt) {
console.log('连接成功');
console.log(evt);
};
//发送消息
websocket.onmessage = function (evt) {
console.log('返回数据');
console.log(evt);
};
//关闭
websocket.onclose = function (evt) {
console.log('关闭');
console.log(evt);
};
//错误
websocket.onerror = function (evt, e) {
console.log('错误');
console.log(evt);
};
</script>
5、创建定时器
<?php
//循环执行,类似setInterval
swoole_timer_tick(1000, function ($timer_id) {
echo 1;
});
//单次执行,类似setTimeout
swoole_timer_after(1000, function () {
echo 2;
});
?>
6、创建异步TCP服务
<?php
//创建TCP服务
$server = new swoole_server('0.0.0.0', 9501);
//设置异步的进程工作数
$server->set(array('task_worker_num' => 5));
//投递异步任务
$server->on('receive', function ($server, $fd, $from_id, $data) {
//异步ID
$task_id = $server->task($data);
echo "异步ID:$task_id\n";
});
//处理异步任务
$server->on('task', function ($server, $task_id, $from_id, $data) {
echo "执行异步ID:$task_id\n";
$server->finish("$data -> OK");
});
//执行完成
$server->on('finish', function ($server, $task_id, $data) {
echo "执行完成\n";
});
//启动服务
$server->start();
?>
7、创建同步TCP客户端
<?php
//客户端tcp
$client = new swoole_client(SWOOLE_SOCK_TCP);
//连接
if (!$client->connect('127.0.0.1', 80, 5)) {
die('连接失败!');
}
//发送数据
if (!$client->send('Hello World!')) {
die('发送数据失败!');
}
//接收数据
$data = $client->recv();
if (!$data) {
die("接收数据失败!");
}
//输出数据
echo $data;
//关闭连接
$client->close();
?>
8、创建异步TCP客户端
<?php
//客户端异步tcp
$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
//连接
$client->on('connect', function ($client) {
$client->send('Hello World!');
});
//接收
$client->on('receive', function ($client, $data) {
echo "Receive:$data\n";
});
//错误
$client->on('error', function ($client) {
echo "Error\n";
});
//关闭
$client->on('close', function ($client) {
echo "Close\n";
});
//发起连接
$client->connect('127.0.0.1', 80, 5);
?>
9、创建子进程事件
<?php
//进程数组
$workers = [];
//进程数
$workers_num = 3;
//创建 启动进程
for ($i = 0; $i < $workers_num; $i++) {
//创建单独进程
$process = new swoole_process('doProcess');
//启动进程,并获取进程ID
$pid = $process->start();
//存入进程数组
$workers[$pid] = $process;
}
//创建进程函数
function doProcess(swoole_process $process) {
//子进程写入信息
$process->write("PID:" . $process->pid);
echo "写入信息:" . $process->pid . '---' . $process->callback . "\n";
}
//添加进程事件 向米格子进程添加需要执行的动作
foreach ($workers as $pid => $process) {
//添加事件
swoole_event_add($process->pipe, function ($pipe) use ($process) {
//读取数据
$data = $process->read();
echo "接收到:" . $data . "\n";
});
}
?>
<?php
//进程数组
$workers = [];
//进程数
$workers_num = 3;
//创建 启动进程
for ($i = 0; $i < $workers_num; $i++) {
//创建单独进程
//$process = new swoole_process('doProcess');
$process = new swoole_process('doProcess', false, false);
//开启队列,类似于全局函数
$process->useQueue();
//启动进程,并获取进程ID
$pid = $process->start();
//存入进程数组
$workers[$pid] = $process;
}
//创建进程函数
function doProcess(swoole_process $process) {
//子进程写入信息
//$process->write("PID:" . $process->pid);
//echo "写入信息:" . $process->pid . '---' . $process->callback . "\n";
$recv = $process->pop(); //默认长度 8192
echo "从主进程获取到数据:" . $recv . "\n";
sleep(5);
$process->exit(0);
}
//添加进程事件 向米格子进程添加需要执行的动作
foreach ($workers as $pid => $process) {
//添加事件
/*swoole_event_add($process->pipe, function ($pipe) use ($process) {
//读取数据
$data = $process->read();
echo "接收到:" . $data . "\n";
});*/
$process->push('Hello 子进程' . $pid . "\n");
}
//等待子进程结束回收资源
for ($i = 0; $i < $workers_num; $i++) {
//等待执行完成
$ret = swoole_process::wait();
$pid = $ret['pid'];
unset($workers[$pid]);
echo "子进程退出" . $pid . "\n";
}
?>
10、创建子进程事件
<?php
//触发函数 异步执行
swoole_process::signal(SIGALRM, function () {
static $i = 0;
echo $i . "\n";
$i++;
if ($i > 10) {
swoole_process::alarm('-1'); //清除定时器
}
});
//开启定时信号
swoole_process::alarm(100 * 100);
?>
11、锁机制
<?php
//创建锁对象
$lock = new swoole_lock(SWOOLE_MUTEX); //互斥锁
echo "创建互斥锁\n";
//锁定
$lock->lock();
if (pcntl_fork() > 0) {
sleep(5);
$lock->unlock(); //解锁
} else {
echo "子进程 等待锁\n";
$lock->lock(); //锁定
echo "子进程获取锁\n";
$lock->unlock();
echo "子进程关闭锁\n";
}
echo "主进程释放锁\n";
unset($lock);
sleep(5);
echo "子进程退出\n";
?>
12、DNS轮询查询
<?php
//DNS轮询查询
swoole_async_dns_lookup('www.baidu.com', function ($host, $ip) {
echo $ip . '-' . $host;
});
?>
13、异步IO
<?php
//异步读取文件
swoole_async_readfile(__DIR__.'/readfile.txt',function($filename,$content){
echo $filename . " - " . $content;
});
?>
<?php
//异步写入
$content = 'Write File Test.';
swoole_async_writefile('writefile.txt',$content,function($filename){
echo $filename;
},0);
?>
<?php
//异步事件:打开资源
$fp = stream_socket_client("tcp://www.qq.com:80",$erron,$errstr,30);
fwrite($fp,"GET / HTTP/1.1\r\nHOST:www.qq.com\r\n\r\n");
//添加异步事件
swoole_event_add($fp,function($fp){
//读取
$resp = fread($fp,8192);
var_dump($resp);
//删除事件
swoole_event_del($fp);
fclose($fp);
});
echo '这个先执行完成'."\n\r";
?>
<?php
//异步mysql操作
$db = new swoole_mysql();
//配置
$config = [
'host' => '139.196.86.20',
'user' => 'root',
'password' => 'llc@126.comllc',
'database' => 'aikehou',
'charset' => 'utf8'
];
//连接数据库
$db->connect($config,function($db,$r){
if($r === false){
//连接失败
var_dump($db->connect_errno,$db->connect_error);
die('连接失败');
} else {
//成功
$sql = 'show tables';
$db->query($sql,function(swoole_mysql $db,$r){
if($r === false){
var_dump($db->error);
die('操作失败');
} else {
var_dump($db->affected_rows,$db->insert_id);
}
var_dump($r);
$db->close();
});
}
});
?>
测试代码:swoole.zip
文明上网理性发言!