Swoole 简单学习(2)
swoole之tcp服务器:
//创建tcp服务器
new swoole_server(string $host,int $port,int $mode=SWOOLE_PROCESS,int $sock_type=SWOOLE_SOCK_TCP);
//事件
bool swoole_server->on(string $event,mixed $callback);
//开启tcp服务器
bool swoole_server->start();
//发送数据
bool swoole_server->send(int $fd,string $data,int $reactorThreadld=0);
function swoole_server->set(array $setting);
参数说明:
//$host的值:内网127.0.0.1、外网ip、0.0.0.0、ipv4或ipv6。
//$port端口:1024以下需要root权限,习惯用9501。
//$mode:默认SWOOLE_PROCESS多进程方式。
//$socl_type:默认SWOOLE_SOCK_TCP。
//$event:
connect建立链接时(回调函数有2个参数:$serv服务器信息、$fd客户端信息);
receive接收到数据(回调函数有4个参数:$serv服务器信息、$fd客户端信息、$from_id客户端id、$data接收的数据);
close关闭连接(回调函数有2个参数:$serv服务器信息、$fd客户端信息);
可以使用网络调式助手软件、要关闭服务器防火墙。
=========================================================================
swoole之udp服务器:
//创建UDP服务器,和创建tcp服务器最后一个参数不一样。
new swoole_server(string $host,int $port,int $mode=SWOOLE_PROCESS,int $sock_type=SWOOLE_SOCK_UDP);
//接收到数据
bool swoole_server->on(string $event,mixed $callback);
$event:'packet',接收数据
//发送数据
bool swoole_server->sendto(string $ip,int $port,string $data,int $server_socket=-1);
示例:
//创建服务
$serv = new swoole_server("0.0.0.0",9502,SWOOLE_PROCESS,SWOOLE_SOCK_UDP);
//监听接收数据
$serv->on('packet',function($serv,$data,$fd){
//发送回去数据
$serv->sendto($fd['address'],$fd['port'],"收到数据:$data");
});
//启动服务
$serv->start();
=======================================================================================
swoole之web服务器
new swoole_http_server();
swoole_http_Server 继承来自swoole_server.
参数1:string $host 监听ip地址
参数2:int $port 监听的端口
on/start函数。
示例:
$serv = new swoole_http_server("0.0.0.0",9501);
//获取请求
$serv->on('request',function($request,$response){
$response->header("Content-Type","text/html;charset=utf-8");//设置返回头
$response->end("hello".json_encode($request));
});
$serv->start();
在浏览器测试:xxx.xxx.xxx.xxx:9501。
======================================================================================
swoole之WebSocket服务器
new swoole_websocket_server();
swoole_websocket_server 继承自swoole_http_server;
on/start函数;
open/message/close;//on函数的事件参数
push()发送数据。
示例:
//服务端
$serv = new swoole_websocket_server("0.0.0.0",9501);
$serv->on('open',function($serv,$client_info){
$serv->push($client_info->fd,"hello");
});
$serv->on('message',function($serv,$client_info){
echo "接收到客户端消息:".$client_info;
$serv->push($client_info->fd,"收到消息");
});
$serv->on('close',function($serv,$client_info){
echo "close".$client_info;
});
$serv->start();
//前端websocket
<script>
var webSocketUrl = "ws://xxx.xxx.xxx.xxx:9501";
var webSocketServer = new WebSocket(webSocketUrl);
webSocketServer.onopen = function(event){
console.log('连接成功');
}
webSocketServer.onclose = function(event){
console.log('关闭');
}
webSocketServer.onmessage = function(event){
console.log(event.data);
}
webSocketServer.onerror = function(event,e){
console.log('错误');
}
</script>
============================================================================
swoole之定时器
js的setInterval()方法
linux的crontab
循环触发函数:
swoole_timer_tick()
参数1:int $after_time_ms 指定时间【毫秒】
参数2:mixed $callback function 执行的函数
参数3:mixed $user_param 用户参数
清除定时器函数:
bool swoole_timer_clear(int $timer_id).
单次触发函数:
swoole_timer_after()
参数与循环触发函数一样。
示例:
循环执行
swoole_timer_tick(3000,function($timer_id){
echo $timer_id;
});
单次执行
swoole_timer_after(3000,function(){
echo '单次';
});
=================================================================================
swoole之异步TCP服务器
task()函数 //投递异步任务
on('事件',function(){}) //异步执行的事件函数
finish()函数 //任务处理完成后结果
示例:
$serv = new swoole_server("0.0.0.0",9501);
//设置异步,进程工作数
$serv->set(array('task_worker_num'=>4));
//投递异步任务
$serv->on("receive",function($serv,$fd,$from_id,$data){
$task_id = $serv->task($data);//异步ID
echo "异步ID:".$task_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 "执行成功";
});
$serv->start();
===========================================================================
swoole之tcp客户端
new swoole_client();
示例:
//创建客户端
$client = new swoole_client(SWOOLE_SOCK_TCP);
//连接服务器
$client->connect('xxx.xxx.xxxx.xxx',9501,5) or die('连接失败');
//发送数据
$client->send('hello') or die('发送失败');
//接收数据
$data = $client->recv();
//关闭客户端
$client->close();
=======================================================================================
swoole之tcp异步客户端
new swoole_client()
SWOOLE_SOCK_TCP //TCP协议
SWOOLE_SOCK_ASYNC //异步支持
示例:
$client = new swoole_client(SWOOLE_SOCK_TCP,SWOOLE_SOCK_ASYNC);
//注册连接成功的回调
$client->on('connect',function($cli){
$cli->send('hello');
});
//注册数据接收
$client->on('receive',function($cli,$data){
echo $data;
});
//注册连接失败
$client->on('error',function($cli){
echo '失败';
});
//注册关闭
$client->on('close',function($cli){
echo '关闭';
});
//发起连接
$client->connect('xxx.xxx.xxx.xxx',9501,10);
==============================================================================
swoole之进程
new swoole_process().
参数1:mixed $function 子进程创建成功后执行的函数。
参数2:$redirect_stdin_stdout 重定向子进程的标准输入输出。启动此选项后,在进程
内echo将不是打印到屏幕,而是写入到管道。读取键盘输入将变成从管道中读取
,默认为阻塞读取。
参数3:$create_pipe 是否创建管道,
$redirect_stdin_stdout后,此选项将忽略用户参数,强制为true,如果子进程内没有
进程间通信,可以设置为false。
示例:
//进程调用的执行函数
function doProcess(swoole_process $worker){
echo "PID".$worker_pid;
}
//创建进程
$process = new swoole_process("doProcess");
$pid = $process->start();
//创建第二个进程
$process = new swoole_process("doProcess");
$pid = $process->start();
//创建第三个进程
$process = new swoole_process("doProcess");
$pid = $process->start();
//等待结束
swoole_process::wait();
=============================================================================
swoole进程事件:
swoole_event_add();
参数1:int $sock
int 文件描述符
mixed $read_callback 就是stream_socket_client/fsockopen 创建的资源
sockets资源,就是sockets扩展中socket_create创建的资源,需要在编译时
加入.configure --enable-sockets
参数2:可读回调函数
示例:
//进程调用的执行函数
function doProcess(swoole_process $worker){
$process->write('pid'.$worker->pid);//子进程写入管道pipe
echo "写入信息:¥worker->pid $worker->callback";
}
$workers = [];//进程池
$worker_num = 3;//进程数量
for($i=0;$i<$worker_num;$i++){
$process = new swoole_process('doProcess');//创建新进程
$pid = $process->start();//启动进程并获取进程id
$workers[$pid] = $process;//放入数组
}
//添加进程事件,向每一个子进程添加需要执行的动作
foreach($workers as $process){
//添加
swoole_event_add($process->pipe,function($pipe) use($process){
$data = $process->read();
echo '接收到'.$data;
})
}
=============================================================================
swoole进程队列通信
string swoole_process->pop(int $maxsize=8192);//取数据
bool swoole_process->push(string $data);//放数据
array swoole_process::wait(bool $blocking=true);
示例:
$workers = [];//进程仓库
$worker_num = 2;//最大进程数
for($i=0;$i<$worker_num;$i++){
$process = new swoole_process('doProcess',false,false);//创建新进程
$process->useQueue();//开启队列,类似于全局函数
$pid = $process->start();//启动进程并获取进程id
$workers[$pid] = $process;//放入数组
}
//进程调用的执行函数
function doProcess(swoole_process $worker){
$recv = $process->pop();//默认8192
echo "从主进程获取导数据:$recv";
sleep(5);
$process->exit(0);
}
//主进程向子进程添加数据
foreach($workers as $pid=>$process){
$process->push("hello 子进程 $pid");
}
//等待子进程结束,回收资源
for($i=0;$i<$worker_num;$i++){
$ret = swoole_process::wait();//等待执行完成
$pid = $ret['pid'];
unset($workers[$pid]);
echo "子进程$pid退出";
}
===============================================================================
进程信号触发器
bool swoole_process::signal(int $signo,callable $callback);
function swoole_process::alarm(int $interval_usec,int $type=ITIMER_REAL):bool.
示例:
//触发函数,异步执行的,
swoole_process::signal(SIGALRM,function(){
echo '123';
});
//定时信号
swoole_process::alarm(100*1000);//100毫秒后执行
//如果达到10次停止
swoole_process::signal(SIGALRM,function(){
static $i=0;
echo '123';
$i++;
if($i>10){
swoole_process::alarm(-1);//清除定时器
}
});
===============================================================================
swoole之锁机制
$lock = new swoole_lock(SWOOLE_MUTEX);
参数:文件锁、读写锁、信号量、互斥锁、自旋锁。
lock();
unlock();
示例:
//创建锁对象
$lock = new swoole_lock(SWOOLE_MUTEX);//互斥锁
echo '创建互斥锁';
$lock->lock();//开始锁定 主进程
if(pcntl_fork() > 0){
sleep(1);
$lock->unlock();//解锁
}else{
echo '子进程在等待锁';
$lock->lock();//上锁
echo "子进程获取锁";
$lock->unlock();//释放锁
exit('子进程退出');
}
echo '主进程释放锁';
unset($lock);
sleep(1);
echo "子进程退出";
================================================================================
swoole之DNS查询
语法:
swoole_async_dns_lookup('域名地址',function($host,$ip));
示例:
swoole_async_dns_lookup('www.baidu.com',function($host,$ip){
echo 'host='.$host .' ip='.$ip;
});
================================================================================
swoole之异步文件读取
语法:
函数方式:
swoole_async_readfile(string $filename,mixed $callback);
面向对象方式:
Swoole\Async::readFile(string $filename,mixed $callback);
示例:
swoole_async_readfile(__DIR__.'/1.txt',function($filename,$content){
echo $filename . ':'.$content;
});
===================================================================================
swoole之异步文件写入
语法:
swoole_async_writefile(string $filename,string $fileContent,
callable $callback=null,int $flags=0);
参数一:文件的名字,必须有可写权限;
参数二:要写入的内容,最大4M;
参数三:写入后的回调函数,可选;
参数四:写入选项,可以使用FILE_APPEND表示追加到文件末尾;
示例:
swoole_async_writefile(__DIR__.'/1.txt','hello',function($filename){
echo $filename;
},0);
==========================================================================================
swoole之异步事件
语法:
bool swoole_event_add(int $sock,mixed $read_callback,mixed $write_callback=null,int $flags=null);
示例:
$fp = stream_socket_client("tcp://www.qq.com:80",$error,$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 "这个是异步的";
==========================================================================================
swoole之异步mysql操作
语法:
swoole_mysql
connect
on
escape
query
示例:
$db = new swoole_mysql();
$config = [
'host' => '192.168.10.1',
'user' => 'root',
'password' => '123456',
'database' => 'mysql',
'charset' => 'utf8'
];
//连接数据
$db->connect($config,function($db,$result){
if($result === false){
var_dump($db->connect_errno,$db->connect_error);
die('失败');
}
//成功
$sql = 'show tables';
$db->query($sql,function(swoole_mysql $db,$res){
if($res === false){
var_dump($db->error);
die('查询失败');
}else if($res === true){
var_dump($db->affected_rows,$db->insert_id);
}
var_dump($res);
$db->close();
});
});
=======================================================================================
swoole之聊天的简单实现:
服务器端代码:
//创建websocket服务器
$ws = new swoole_websocket_server("0.0.0.0",9502);
$ws->on('open',function($ws,$request){
echo '新用户:'.$request->fd .'加入';
//设置用户id,存入全局变量
$GLOBALS['fd'][$request->fd]['id'] = $request->fd;
$GLOBALS['fd'][$request->fd]['name'] = '匿名用户';
});
$ws->on('message',function($ws,$request){
$msg = $GLOBALS['fd'][$request->fd]['name'].":".$request->data."\n";
if(strstr($request->data,"#name#")){
//用户设置昵称
$GLOBALS['fd'][$request->fd]['name'] = str_replace("#name#",'',$request->data);
}else{
//发送给每一个客户端
foreach($GLOBALS['fd'] as $val){
$ws->push($val['id'],$msg);
}
}
});
$ws->on('close',function(){
echo '客户端断开连接:'.$request;
unset($GLOBALS['fd'][$request]);
});
$ws->start();
客户端:
引入jquery.js、webSocket.js。
var msg = document.getElementById('msg');
var wsSwever = 'ws://192.168.10.1:9502';
var websocket = new WebSocket(wsServer);
websocket.onopen = function(evt){
//显示登录服务器成功
//msg.innerHTML = websocket.readState;
//websocket.readState属性:
//CONNECTING 0 The connection is not yet open.
//OPEN 1 The connection is open and ready to communite.
//CLOSEING 2 The connection is in the process of closing。
//CLOSED 3 The connection is closed or couldn't be opened.
}
websocket.onmessage = function(evt){
msg.innerHTML += evt.data +'<br>';//不断递增的数据
console.log('从服务器获取到的数据:'+evt.data);
};
//监听连接关闭
websocket.onclose = function(evt){
console.log('服务器拒绝');
};
//监听连接错误信息
websocket.onerror = function(evt){
console.log('错误:'.evt.data);
}
//发送信息
function send_msg(){
var text = document.getElementById('text').value;//获取数据
websocket.send(text);
document.getElementById('text').value = '';
}
//发送昵称
function send_name(){
var text = document.getElementById('text').value;//获取数据
websocket.send("#name#"+text);//向服务器发送数据
document.getElementById('text').value = '';
var myTitle = document.getElementById("myTitle");
myTitle.innerHtml = "IM "+text;
alert("设置成功");
}