swoole创建tcp服务的一次实战

1.安装swoole扩展 具体查看   swoole安装步骤

2.看相关swoole文档 实现tcp服务

代码

tcp.php

<?php
/**
 * User: may
 * Date: 2019/6/4
 * Time: 下午2:52
 */
//创建server对象 监听127.0.0.1
$serv=new swoole_server("127.0.0.1","9501");

$serv->set([
    'reactor_num' => 111, //reactor thread num
    'worker_num' => 8,    //worker process num 进程数 建议等于开启cpu核数的1-4倍
    'max_request' => 10000, //每个进程处理的最大用户数

]);
//监听进入事件
$serv->on('connect',function ($serv,$fd,$reactor_id){
    echo "Client:{$reactor_id}-{$fd}Connet!!.\n";
});

//监听数据接收事件
/**
 * $fd客户端链接的唯一标识
 */
$serv->on('receive',function ($serv,$fd,$reactor_id,$data){
    $serv->send($fd,"server:{$reactor_id}-{$fd}".$data);
});


//监听连接关闭事件
$serv->on('close',function ($serv,$fd){
   echo 'Client:Close.\n';
});


//启动服务器
$serv->start();

3.测试

 打开终端

执行  php tcp.php

使用 netstat -an|grep 9501 命令

查看9501端口服务是否开启

开启新终端

执行  客户端连接到服务  telnet 127.0.0.1 9501

 

多开启几个客户端连接到服务端

 

关闭服务端

客户端也随之关闭

 

 

 

 

启动一个http_server服务 并测试

http_server.php

 

 

 

 

 

 例子3 通过http_server请求html页面

<?php
/**
 * User: may
 * Date: 2019/6/5
 * Time: 上午11:18
 */
$http = new swoole_http_server("0.0.0.0", 8811);//0.0.0.0表示监听所有地址

$http->set(
    [
        'enable_static_handler'=>true,
        'document_root'=>"/Applications/MAMP/htdocs/swoole_code/data/", //html文件目录

    ]);

$http->on('request', function ($request, $response) {
    print_r($request->get);
    $response->cookie("admin_name","ssss",time()+1800);
    $response->end("<h1>http server Data :</h1>".json_encode($request->get)); //数据要显示到浏览器 需要把数据放在end 方法

});

$http->start();

 

 

 

 例子4  通过http_server.php  启动服务

ws_server.php 推送消息

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ws_client测试</title>
</head>
<body>
<h1>hill ws测试</h1>
<script>
    var wsUrl = 'ws://127.0.0.1:8813';

    var websocket = new WebSocket(wsUrl);

    //实例对象onopen属性
    websocket.onopen = function (evt) {
        websocket.send('hello hill');
        console.log("conneted success ");
    }

    //实例化 onmessage

    websocket.onmessage = function (evt) {
        console.log("ws-sever-return-data is : " + evt.data);
    }

    //onclose
    websocket.onclose=function (evt) {
        console.log("cloese");
    }
    //onerror
    websocket.onerror=function (evt,e) {
        console.log("error:"+evt.data);
    }
</script>
</body>
</html>

ws_server.php

<?php
/**
 * User: may
 * Date: 2019/6/5
 * Time: 下午2:15
 */
$server = new swoole_websocket_server ("0.0.0.0", 8813);

$server->set(
    [
        'enable_static_handler'=>true,
        'document_root'=>"/Applications/MAMP/htdocs/swoole_code/data/",

    ]);

//监听websocket 连接打开事件
$server->on('open', 'onOpen');
function onOpen($server,$request){
    print_r($request->fd);

}

//监听websocket 消息事件
/**$fd 客户端连接的ID,如果指定的$fd对应的TCP连接并非websocket客户端,将会发送失败
$data 要发送的数据内容
$opcode,指定发送数据内容的格式,默认为文本。发送二进制内容$opcode参数需要设置
 * */
$server->on('message', function (swoole_websocket_server $server, $frame) {
    echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
    $server->push($frame->fd,  "hello websocket server push success"); //把数据push到客户端
});

$server->on('close', function ($ser, $fd) {
    echo "client {$fd} closed\n";
});

$server->start();

 

例子4.

task和push异步执行任务

<?php

/**
 * User: may
 * Date: 2019/6/5
 * Time: 下午3:42
 * ws 基础类库优化
 */
class ws
{

    const HOST = "0.0.0.0";
    const PORT = 8813;

    public $ws = null;

    public function __construct()
    {
        $this->ws = new swoole_websocket_server ("127.0.0.1", 8813);

        $this->ws->set([
            'worker_num'=>2,
            'task_worker_num'=>2,
        ]);

        $this->ws->on("open", [$this, 'onOpen']);
        $this->ws->on("message", [$this, 'onMessage']);
        $this->ws->on("task", [$this, 'onTask']);
        $this->ws->on("finish", [$this, 'onFinish']);
        $this->ws->on("close", [$this, 'onClose']);

        $this->ws->start();
    }

    /**
     * 监听ws连接事件
     * @param $ws
     * @param $request
     */
    public function onOpen($ws, $request)
    {
        var_dump($request->fd);
    }


    /**
     * 监听ws消息事件
     * @param $ws
     * @param $frame
     */
    public function onMessage($ws, $frame)
    {
        echo "sever-push-message:{$frame->data}\n";//来自客户端发的数据
        //todo 10s
        $data = [
            'task' => 1,
            'fd' => $frame->fd,
        ];
        $ws->task($data);//本来应该先执行task 在执行push 但是 异步操作 所以push不必等task执行完再执行 而是同步进行 所以很快
        $ws->push($frame->fd, "server-push:" . "sever data 2019");//server推送数据给客户端
    }

    /**
     * @param $serv
     * @param $taskId
     * @param $workerId
     * @param $data
     */
    public function onTask($ws, $taskId, $workerId, $data)
    {
        echo "Tasker进程接收到数据\n";
        print_r($data);
       //耗时场景10s
        sleep(10);
        return " on task finish";
    }

    /**
     * @param $serv
     * @param $taskId
     * @param $data onTask方法return的值
     */
    public function onFinish($ws, $taskId, $data)
    {
        echo "taskId:{$taskId}\n";
        echo "finish-data-success:{$data}\n";

    }

    /**
     *
     * @param $ws
     * @param $fd
     */
    public function onClose($ws, $fd)
    {
        echo "closed client_id:{$fd}\n";
    }

}

$obj = new ws();

 

终端在相关目录执行

php http_server

php ws.php

浏览器打开 http://127.0.0.1:8811/ws_client.html

代码中应该先执行task  再执行push  task要停留10s 但是客户端收到push的消息很快远小于10s

这就是异步处理机制

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

多进程执行

<?php
/**
 * User: may
 * Date: 2019/6/14
 * Time: 下午5:24
 */
echo "process-start-time" . date('Y-m-d H:i:s', time()) . PHP_EOL;
$wokers = [];
$urls = [
    'http://baidu.com',
    'http://wiki.swoole.com',
    'http://qq.com',
    'http://sina.com',
    'https://www.jd.com',
    'https://www.taobao.com'
];

//传统php 做法
//foreach ($urls as $url) {
//    $contents[] = file_get_contents($urls);
//}

//并不是 耗时6秒 而是1秒 6个进程同时进行
for ($i = 0; $i < 6; $i++) {
    $process = new swoole_process(function (swoole_process $worker) use ($i, $url) {
        $content = curlData($url[$i]);
        echo $content . PHP_EOL;
       // $worker->write($content);
    }, true); //true 就到管道 false到屏幕
    $pid = $process->start();
    $wokers[$pid] = $process;
}

foreach ($wokers as $process) {
    echo $process->read();
}


//获取url里面内容
function curlData($url)
{
    //file_get_contents();
    sleep(1);
    return $url . "sucess" . PHP_EOL;

}

echo "process-end-time" . date('Y-m-d H:i:s', time()) . PHP_EOL;

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芝麻开门2015

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值