swoole
centos 7.4 php5.6安装swoole
pecl install swoole
The latest version will be installed
pecl install http://pecl.php.net/get/swoole-2.0.11.tgz
以上php5.6安装swoole,在php.ini开启扩展,php-fpm无法启动,官网提示:
采用php-7.0 或更高版本安装
将php切换到PHP Version 7.0.32版本,采用手动编译模式又来了一次安装,swoole4.2.9版本,命令行如下:
①cd /usr/local/src //切换某个文件夹下 ②wget http://pecl.php.net/get/swoole-4.2.9.tg //下载swoole包 ③tar -zvxf swoole-4.2.9.tgz //解压 ④cd swoole-4.2.9 ⑤/www/server/php/70/bin/phpize //phpize是用来扩展php扩展模块的,通过phpize可以建立php的外挂模块 ⑥./configure --with-php-config=/www/server/php/70/bin/php-config ⑦make && make install 安装成功提示: Build complete. Don't forget to run 'make test'. Installing shared extensions: /www/server/php/70/lib/php/extensions/no-debug-non-zts-20151012/ Installing header files: /www/server/php/70/include/php/ ⑧php.ini启用扩展 extension=swoole.so |
恭喜,swoole安装成功!
创建TCP服务器
<?php //创建Server对象 /* * $host参数用来指定监听的ip地址,如127.0.0.1,或者外网地址,或者0.0.0.0监听全部地址 * $port监听的端口,如9501 * 如果$sock_type为UnixSocket Stream/Dgram,此参数将被忽略 * 监听小于1024端口需要root权限 * 如果此端口被占用server->start时会失败 */ $host="0.0.0.0"; $port=9501; $serv = new swoole_server($host, $port); /* Server->on回调参数说明 * $serv swoole_server对象 * $fd 连接的描述符 * $from_id reactor的id * $data 接收到的数据 / /*监听连接连接事件*/ $serv->on('connect', function ($serv, $fd) { echo "Client: Connect.\n"; }); /*监听数据接收事件*/ $serv->on('receive', function ($serv, $fd, $from_id, $data) { $serv->send($fd, "Server: ".$data); }); //监听连接关闭事件 $serv->on('close', function ($serv, $fd) { echo "Client: Close.\n"; }); //启动服务器 $serv->start(); ?> |
注意:1024以下端口:需要root权限,本示例采用9501端口
①防火墙必须关闭 systemctl stop firewalld.service
②php 启用文件
添加防火墙9501端口 firewall-cmd --zone=public --add-port=9501/tcp --permanent (--permanent永久生效,没有此参数重启后失效,开启成功后会提示success) php cli模式模式下运行php文件,启动swoole服务 php server.php netstat -an | grep 9501 //查看端口是否监听的命令 tcp 0 0 127.0.0.1:9501 0.0.0.0:* LISTEN 查看所有打开的端口 firewall-cmd --list-all 查看防火墙的状态 firewall-cmd --state 停止防火墙 systemctl stop firewalld.service 查看监听进程 ps -ajft 杀死某个端口下的进程 sudo fuser -k -n udp 9501 sudo fuser -k -n tcp 9501
端口参考:https://www.cnblogs.com/moxiaoan/p/5683743.html
socket调试助手
命令台显示
成功!
创建UDP服务器
<?php /*************创建UDP服务器 ********************/ /* * SWOOLE_PROCESS 多进程模式 * SWOOLE_SOCK_UDP 创建udp socket */ $serv=new swoole_server('0.0.0.0',9501,SWOOLE_PROCESS,SWOOLE_SOCK_UDP); /*数据监听接收事件 *$serv 服务端信息 *$data 接收到的数据 *$fd 客户端信息 */ $serv->on('packet',function($serv,$data,$fd){ echo 'here'; $serv->sendto($fd['address'],$fd['port'],'server:message'); }); $serv->start(); ?> |
udp调试,失败~~~
创建web服务器
<?php $host='0.0.0.0'; $port=9501; $serv=new swoole_http_server($host,$port); /* * $request 请求信息 * $response 响应信息 */ $serv->on('request',function($request,$response){ var_dump($request); $response->header('content-type','text/html;charset:utf-8'); $response->end('hello'.time()); }); $serv->start(); ?> |
打印$request如下:
object(Swoole\Http\Request)#6 (9) { ["fd"]=> int(2) ["header"]=> array(8) { ["host"]=> string(16) "47.52.23.66:9501" ["connection"]=> string(10) "keep-alive" ["cache-control"]=> string(9) "max-age=0" ["upgrade-insecure-requests"]=> string(1) "1" ["user-agent"]=> string(110) "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36" ["accept"]=> string(85) "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp ,image/apng,*/*;q=0.8" ["accept-encoding"]=> string(13) "gzip, deflate" ["accept-language"]=> string(14) "zh-CN,zh;q=0.9" } ["server"]=> array(11) { ["request_method"]=> string(3) "GET" ["request_uri"]=> string(1) "/" ["path_info"]=> string(1) "/" ["request_time"]=> int(1545222695) ["request_time_float"]=> float(1545222695.4996) ["server_port"]=> int(9501) ["remote_port"]=> int(47183) ["remote_addr"]=> string(12) "111.37.29.67" ["master_time"]=> int(1545222695) ["server_protocol"]=> string(8) "HTTP/1.1" ["server_software"]=> string(18) "swoole-http-server" } ["request"]=> NULL ["cookie"]=> array(21) { ["serverType"]=> string(6) "apache" ["order"]=> string(7) "id desc" ["uploadSize"]=> string(10) "1073741824" ["rank"]=> string(1) "a" ["memRealUsed"]=> string(3) "572" ["mem-before"]=> string(12) "572/992 (MB)" ["memSize"]=> string(3) "992" ["upNet"]=> string(1) "0" ["downNet"]=> string(1) "0" ["one"]=> string(4) "0.08" ["five"]=> string(4) "0.16" ["fifteen"]=> string(3) "0.1" ["conterError"]=> string(0) "" ["apacheVersion"]=> string(0) "" ["phpVersion"]=> string(1) "0" ["pnull"]=> string(1) "2" ["SetId"]=> string(9) "inputPath" ["SetName"]=> string(0) "" ["ChangePath"]=> string(1) "4" ["Path"]=> string(33) "/www/wwwroot/wuxinzhe/test/swoole" ["BT_PANEL"]=> string(40) "7bddbb2fd05f6f870ce652fa106b2df18e2d02aa" } ["get"]=> NULL ["files"]=> NULL ["post"]=> NULL ["tmpfiles"]=> NULL } |
访问web服务器如下:
创建websocket服务器
<?php /*****创建websocket服务器******/ $host='0.0.0.0'; $port=9501; $ws=new swoole_websocket_server($host,$port); //swoole_websocket_server继承自swoole_http_server //open建立连接 $ws服务器 $request客户端请求信息 $ws->on('open',function($ws,$request){ var_dump($request); $ws->push($request->fd,'welcome \n'); }); //message 接收信息 $ws->on('message',function($ws,$request){ $ws->push($request->fd,'i get message \n'); }); //close 关闭连接 $ws->on('close',function($ws,$request){ echo 'connection close'; }); $ws->start(); ?> |
前端html访问文件
<!DOCTYPE html> <html> <head> <script type="text/javascript"> var wsServer='ws://47.52.23.66:9501'; var webSocket=new WebSocket(wsServer); webSocket.onopen=function(evt){ console.log('connect'); } webSocket.onmessage=function(evt){ console.log(evt); console.log(evt.data); } webSocket.onclose=function(evt){ console.log('connect close'); } webSocket.onerror=function(evt){ console.log('connect error'); } </script> </head> <body> </body> </html> |
访问http://111.230.6.126/test/swoole/4.html,谷歌控制台输出如下:
命令行输出(也就是$request)如下:
object(Swoole\Http\Request)#8 (9) { ["fd"]=> int(1) ["header"]=> array(12) { ["host"]=> string(16) "47.52.23.66:9501" ["connection"]=> string(7) "Upgrade" ["pragma"]=> string(8) "no-cache" ["cache-control"]=> string(8) "no-cache" ["upgrade"]=> string(9) "websocket" ["origin"]=> string(19) "http://111.230.6.126" ["sec-websocket-version"]=> string(2) "13" ["user-agent"]=> string(110) "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36" ["accept-encoding"]=> string(13) "gzip, deflate" ["accept-language"]=> string(14) "zh-CN,zh;q=0.9" ["sec-websocket-key"]=> string(24) "xI/WejWs8gYEoUh/ppJiMw==" ["sec-websocket-extensions"]=> string(42) "permessage-deflate; client_max_window_bits" } ["server"]=> array(11) { ["request_method"]=> string(3) "GET" ["request_uri"]=> string(1) "/" ["path_info"]=> string(1) "/" ["request_time"]=> int(1545225761) ["request_time_float"]=> float(1545225761.7432) ["server_port"]=> int(9501) ["remote_port"]=> int(31280) ["remote_addr"]=> string(12) "111.37.29.67" ["master_time"]=> int(1545225761) ["server_protocol"]=> string(8) "HTTP/1.1" ["server_software"]=> string(18) "swoole-http-server" } ["request"]=> NULL ["cookie"]=> array(21) { ["serverType"]=> string(6) "apache" ["order"]=> string(7) "id desc" ["uploadSize"]=> string(10) "1073741824" ["rank"]=> string(1) "a" ["memRealUsed"]=> string(3) "572" ["mem-before"]=> string(12) "572/992 (MB)" ["memSize"]=> string(3) "992" ["upNet"]=> string(1) "0" ["downNet"]=> string(1) "0" ["one"]=> string(4) "0.08" ["five"]=> string(4) "0.16" ["fifteen"]=> string(3) "0.1" ["conterError"]=> string(0) "" ["apacheVersion"]=> string(0) "" ["phpVersion"]=> string(1) "0" ["pnull"]=> string(1) "2" ["SetId"]=> string(9) "inputPath" ["SetName"]=> string(0) "" ["ChangePath"]=> string(1) "4" ["Path"]=> string(33) "/www/wwwroot/wuxinzhe/test/swoole" ["BT_PANEL"]=> string(40) "7bddbb2fd05f6f870ce652fa106b2df18e2d02aa" } ["get"]=> NULL ["files"]=> NULL ["post"]=> NULL ["tmpfiles"]=> NULL }
swoole定时器
<?php //循环触发 定时器 /** * 参数1 指定多少时间后触发(毫秒) * 参数2 执行的函数 * 参数3 用户参数 */ swoole_timer_tick(2000,function($time_id){ echo $time_id."循环执行 \n"; }); //单次执行 swoole_timer_after(0050,function(){ echo "单次执行 \n"; }); ?> |
命令行输出如下:
TCP异步服务器
<?php //异步TCP服务器 $host='0.0.0.0'; $port=9501; $serv=new swoole_server($host,$port); //设置异步进程工作数 $serv->set(array('task_worker_num'=>4)); //投递异步任务 $serv->on('receive',function($serv,$fd,$from_id,$data){ echo $data; $task_id=$serv->task($data); //获取异步ID }); //处理异步任务 $serv->on('task',function($serv,$task_id,$from_id,$data){ echo "执行异步ID:$task_id"; $serv->finish("$data->OK"); }); $serv->on('finish',function ($serv,$task_id,$data){ echo '执行结束'.$task_id; }); $serv->start(); ?> |
命令行运行脚本,发送tcp数据,输出如下:
wuxinzhe执行异步ID:0执行结束0wuxinzhe执行异步ID:1执行结束1wuxinzhe执行异步ID:2执行结束2
TCP客户端(未测)
<?php $client = new swoole_client(SWOOLE_SOCK_TCP); if (!$client->connect('127.0.0.1',9501, -1)) { exit("connect failed. Error: {$client->errCode}\n"); } $client->send("hello world\n"); echo $client->recv(); $client->close(); ?> |
进程(未学)
锁机制
<?php //创建锁对象 $lock=new swoole_lock(SWOOLE_MUTEX); //互斥锁 SWOOLE_MUTEX //自旋锁 SWOOLE_SPINLOCK //读写锁 SWOOLE_RWLOCK //文件锁 SWOOLE_FILELOCK //信号量 SWOOLE_SEM echo "创建互斥锁 \n"; $lock->lock(); //开始锁定主进程 if(pcntl_fork()>0){ //pcntl_fork()函数创建一个子进程,这个子进程仅PID(进程号) 和PPID(父进程号)与其父进程不同。 sleep(2); $lock->unlock(); //解锁 }else{ sleep(2); echo "子进程等待锁\n"; $pid=$lock->lock(); echo "子进程{$pid}获取锁 \n"; $lock->unlock(); echo "释放锁 \n"; } ?> |
cli下运行如下:
[root@izj6cchtb8a3ve65l62cchz swoole]# php 8.php 创建互斥锁 [root@izj6cchtb8a3ve65l62cchz swoole]# 子进程等待锁 子进程1获取锁 释放锁
DNS查询
<?php //DNS查询 swoole_async_dns_lookup('wuxinzhe.top',function($host,$ip){ echo "host:$host \n"; echo "ip:$ip \n"; }); ?> |
cli模式下输出如下:
host:wuxinzhe.top ip:47.52.23.66
异步读取文件
<?php //异步读取文件 swoole_async_readfile('4.html',function ($fileName,$content){ echo $fileName.':'.$content; }); ?> |
异步写入文件
<?php /*异步写入文件 参数1为文件的名称,必须有可写权限,文件不存在会自动创建。打开文件失败会立即返回false 参数2为要写入到文件的内容,最大可写入4M 参数3为写入成功后的回调函数,可选 参数4为写入的选项,可以使用FILE_APPEND表示追加到文件末尾 如果文件已存在,底层会覆盖旧的文件内容*/ $content="something write to swoole"; swoole_async_writefile('1.txt',$content, function($filename) { echo "wirte ok.\n"; }, 0); ?> |
swoole异步事件
<?php //swoole异步事件 $fp=stream_socket_client('tcp://www.qq.com:80',$errno,$errstr,50); fwrite($fp,"GET / HTTP/1.1\r\nHost: www.qq.com\r\n\r\n"); swoole_event_add($fp,function ($fp){ $resp=fread($fp,8000); var_dump($resp); swoole_event_del($fp); fclose($fp); }); echo "这个先执行完成 \n"; ?> |
swoole异步mysql
<?php //异步mysql $db=new swoole_mysql(); $config=array( 'host'=>'127.0.0.1', 'user'=>'wuxinzhe', 'password'=>'******', 'database'=>'wuxinzhe', 'charset'=>'utf8' ); $db->connect($config,function($db,$r){ if($r===false){ var_dump($db->connect_errno,$db->connect->error); die('连接mysql失败'); } $sql='show tables'; $db->query($sql,function(swoole_mysql $db,$r){ if($r===false){ echo '失败'; var_dump($db->error); die('操作失败'); } var_dump($r); $db->close(); }); }); ?> |
运行以下代码,提示:Swoole\Coroutine\MySQL::connect: API must be called in the coroutine
$swoole_mysql = new Swoole\Coroutine\MySQL(); $swoole_mysql->connect([ 'host' => '127.0.0.1', 'port' => 3306, 'user' => 'tao2345', 'password' => '5ZcTMeZA2z7zkarf', 'database' => 'tao2345', ]); $res = $swoole_mysql->query('select * from `order`'); var_dump($res); |
[2019-07-24 15:08:47 @22613.0] ERROR (PHP Fatal Error: 10001): Swoole\Coroutine\MySQL::connect: API must be called in the coroutine Stack trace: #0 Swoole\Coroutine\MySQL->connect() called at [/www/wwwroot/360buy/application/swoole/controller/Index.php:7] |
需要放在协程中运行
go(function() { $swoole_mysql = new Swoole\Coroutine\MySQL(); $swoole_mysql->connect([ 'host' => '127.0.0.1', 'port' => 3306, 'user' => 'tao234115', 'password' => '115ZcTMeZA2z7zkarf', 'database' => 'tao112345', ]); $res = $swoole_mysql->query('select * from `order`'); var_dump($res); }); |