十、Swoole 基础学习笔记 - Swoole Server 监听多端口服务

作者: 温新

分类: 【Swoole 系列】

阅读: 921

时间: 2023-02-27 07:49:23

hi,我是温新,一名PHPer

文章基于 Swoole 5.0.1 版本编写。

**学习目标:了解 Swoole Server 多端口的使用及其使用场景 **

说明:本篇文章结合官方文档编写及参考网络资料编写,虽非全部原创,但也是结合了自己的理解,若转载请附带本文 URL,编写不易,持续编写更不易,谢谢!

为什么需要使用多端口

在实际环境中,可能一个服务可能需要提供不同的功能服务,如此,在一个服务中可以根据不同的端口提供不同的服务。Swoole 中 使用 listen 实现多端口的监听。

listen 多端口监听

listen 初体验

服务端多端口案例

<?php
// 6-swoole-server-listen-1.php
$server = new Swoole\Server('0.0.0.0', 9501, SWOOLE_PROCESS);

$server->set([
    'worker_num'  => 3,
    'reactor_num' => 3,
]);

// 绑定一个新的端口 9502
$server->listen('0.0.0.0', 9502, SWOOLE_SOCK_TCP);

$server->on('Connect', function ($server, $fd, $reactorId) {
    // 输出来自于哪个端口
    echo $server->getClientInfo($fd)['server_port'] . PHP_EOL;
});

$server->on('Receive', function ($server, $fd, $reactorId, $data) {
    $server->send($fd, 'Server:' . $data);
});

$server->start();

怎么确定是否启动了 2 个端口?

$netstat -nltp                 
tcp        0      0 0.0.0.0:9501            0.0.0.0:*               LISTEN      65830/php           
tcp        0      0 0.0.0.0:9502            0.0.0.0:*               LISTEN      65830/php 

在这个案例中,监听了一个新的端口 9501,那么多端口连接时,信息是如何处理的?若没有对新绑定的端口进行绑定新的回调,那么会共享已给出的回调。下面给出两个客户端来验证:

<?php
// 6-swoole-server-listen-client-9501.php
$client = new Swoole\Client(SWOOLE_SOCK_TCP);

if (!$client->connect('127.0.0.1', 9501, -1)) {
	exit('连接服务器失败' . $client->errCode . PHP_EOL);
}

$client->send('i am 9501 port');

echo $client->recv() . PHP_EOL;

$client->close();
<?php
// 6-swoole-server-listen-client-9502.php
$client = new Swoole\Client(SWOOLE_SOCK_TCP);

if (!$client->connect('127.0.0.1', 9502, -1)) {
	exit('连接服务器失败' . $client->errCode . PHP_EOL);
}

$client->send('i am 9502 port');

echo $client->recv() . PHP_EOL;

$client->close();

listen 服务处理

多端口已经准备好,那么现在开始不同的服务走不同的端口处理不同的业务。下面对服务端代码进程调整:

// 6-swoole-server-listen-1.php
$server->on('Receive', function ($server, $fd, $reactorId, $data) {
    $port = $server->getClientInfo($fd)['server_port'];
    if ($port == 9501) {
        $server->send($fd, $port . ' 你的 websockert 任务正在处理');
    } else {
        $server->send($fd, $port . ' 你的 AI 任务正在处理');
    }
});

listen 多端口区分处理任务

<?php

$server = new Swoole\Server('0.0.0.0', 9501, SWOOLE_PROCESS);

$server->set([
    'worker_num'  => 3,
    'reactor_num' => 3,
]);

// 绑定一个新的端口 9502
$portServer = $server->listen('0.0.0.0', 9502, SWOOLE_SOCK_TCP);

// 单品为绑定的新端口添加回调
$portServer->on('Receive', function ($portServer, $fd, $reactorId, $data) {
    echo $portServer->send($fd, '9502 VIP 服务通道,为 ' . $fd . '开启');
});

// 处理 9501 任务
$server->on('Connect', function ($server, $fd, $reactorId) {
});

$server->on('Receive', function ($server, $fd, $reactorId, $data) {
    echo $server->send($fd, '普通服务处理, ' . $fd . '-' . $data);
});

$server->start();

多端口混合协议监听

上面的多端口案例中,有一个弊端,那就是两个端口都是使用同一种协议。再如,这两个端口现在要提供完全不一样的服务,如 9501 端口使用 rpc 协议,9502 端口使用 tcp 协议。现在来看看处理案例:

<?php
// 6-swoole-server-listen-3.php
$server = new Swoole\Server('0.0.0.0', 9501, SWOOLE_PROCESS);

$server->set([
	'worker_num'  => 3,
	'reactor_num' => 3,
]);

// 监听不同的端口
$portServer1 = $server->listen('0.0.0.0', 9502, SWOOLE_SOCK_TCP);
$portServer2 = $server->listen('0.0.0.0', 9503, SWOOLE_SOCK_UDP);

// 为不同的端口配置参数
$portServer1->set([
	// 开启固定包头协议
	'open_length_check'     => true,
	'package_length_type'   => 'N',
	'package_length_offset' => 0,
	'package_max_length'    => 80000,
]);

$portServer2->set([
	'open_eof_split' => true,
	// 设置消息结束符
	'package_eof'    =>	'eof',  
]);

$server->on('Receive', function ($server, $fd, $reactorId) {
});

// UDP 协议接收数据
$server->on('Packet', function ($portServer2, $data, $clientInfo) {
});

$server->start();

我是温新,本篇文章到此结束,下一篇文章继续学习。

请登录后再评论