Server可以监听多个端口,每个端口都可以设置不同的协议处理方式,例如80端口处理http协议,9507端口处理TCP协议。SSL/TLS传输加密也可以只对特定的端口启用。
!> 例如主服务器是WebSocket或Http协议,新监听的TCP端口(listen的返回值,即Swoole\Server\Port,以下简称port)默认会继承主Server的协议设置。必须单独调用port对象的set方法和On方法设置新的协议才会启用新协议,port对象的set和on方法,使用方法与基类Swoole\Server完全一致。如下:
监听新端口
//返回port对象
$port1 = $server->listen("127.0.0.1", 9501, SWOOLE_SOCK_TCP);
$port2 = $server->listen("127.0.0.1", 9502, SWOOLE_SOCK_UDP);$port3 = $server->listen("127.0.0.1", 9503, SWOOLE_SOCK_TCP | SWOOLE_SSL);
设置网络协议//port对象的调用set方法
$port1->set(['open_length_check' => true,
'package_length_type' => 'N',
'package_length_offset' => 0,
'package_max_length' => 800000,
]);
$port3->set([
'open_eof_split' => true,
'package_eof' => "\r\n",
'ssl_cert_file' => 'ssl.cert',
'ssl_key_file' => 'ssl.key',
]);
设置回调函数
//设置每个port的回调函数
$port1->on('connect', function ($serv, $fd){echo "Client:Connect.\n";
});
$port1->on('receive', function ($serv, $fd, $from_id, $data) {
$serv->send($fd, 'Swoole: '.$data);
$serv->close($fd);
});
$port1->on('close', function ($serv, $fd) {
echo "Client: Close.\n";
});
$port2->on('packet', function ($serv, $data, $addr) {
var_dump($data, $addr);
});
Http/WebSocket
Swoole\Http\Server和Swoole\WebSocket\Server因为是使用继承子类实现的,无法通过调用Swoole\Server实例的listen来方法创建Http或者WebSocket服务器。如果服务器的主要功能为RPC,但希望提供一个简单的Web管理界面。
在这样的场景中,可以先创建Http/WebSocket服务器,然后再进行listen监听原生TCP的端口。
示例
$http_server = new Swoole\Http\Server('0.0.0.0',9998);
$http_server->set(array('daemonize'=> false));$http_server->on('request','request');
//......设置各个回调......//多监听一个tcp端口,对外开启tcp服务,并设置tcp服务器的回调
$tcp_server = $http_server->addListener('0.0.0.0', 9999, SWOOLE_SOCK_TCP);
//默认新监听的端口 9999 会继承主服务器的设置,也是 Http 协议
//需要调用 set 方法覆盖主服务器的设置
$tcp_server->set(array());
$tcp_server->on("receive", function ($serv, $fd, $threadId, $data) {echo $data;
});
通过这样的代码,我们便可以建立一个同时对外提供http服务,又同时对外提供tcp服务的server,具体更加的优雅代码组合则由你自己来实现。TCP、Http、WebSocket多协议端口复合设置
$port1 = $server->listen("127.0.0.1", 9501, SWOOLE_SOCK_TCP);
$port1->set(['open_websocket_protocol' => true, // 设置使得这个端口支持WebSocket协议
]);$port1 = $server->listen("127.0.0.1", 9501, SWOOLE_SOCK_TCP);
$port1->set([
'open_http_protocol' => false, // 设置这个端口关闭http协议功能
]);
同理还有: open_http_protocol、open_http2_protocol、open_mqtt_protocol 等参数可选参数
监听端口port未调用set方法,设置协议处理选项的监听端口,将会继承主服务器的相关配置
主服务器为Http/WebSocket服务器,如果未设置协议参数,监听的端口仍然会设置为Http或WebSocket协议,并且不会执行为端口设置的onReceive回调
主服务器为Http/WebSocket服务器,监听端口调用set设置配置参数,会清除主服务器的协议设定。监听端口将变为TCP协议。监听的端口如果希望仍然使用Http/WebSocket协议,需要在配置中增加open_http_protocol => true 和 open_websocket_protocol => true
port可以通过set设置的参数有:socket参数:如backlog、TCP_KEEPALIVE、open_tcp_nodelay、tcp_defer_accept等
协议相关:如open_length_check、open_eof_check、package_length_type等
SSL证书相关:如ssl_cert_file、ssl_key_file等
具体参考可配置章节可选回调
port未调用on方法,设置回调函数的监听端口,默认使用主服务器的回调函数,port可以通过on方法设置的回调有:TCP服务器
onConnect
onClose
onReceive
UDP服务器
onPacket
onReceive
Http服务器
onRequest
WebSocket服务器
onMessage
onOpen
onHandshake
!> 不同监听端口的回调函数,仍然是相同的Worker进程空间内执行多端口下的连接遍历
<?php
$server = new Swoole\WebSocket\Server("0.0.0.0", 9514, SWOOLE_BASE);
$tcp = $server->listen("0.0.0.0", 9515, SWOOLE_SOCK_TCP);
$server->on("open", function ($serv, $req) {
echo "new WebSocket Client, fd={$req->fd}\n";
});
$server->on("message", function ($serv, $frame) {
echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
$serv->push($frame->fd, "this is server OnMessage");
});
$tcp->on('receive', function ($server, $fd, $reactor_id, $data) {
//仅遍历 9514 端口的连接,因为是用的$server,不是$tcp
$websocket = $server->ports[0];
foreach ($websocket->connections as $_fd) {
var_dump($_fd);
if ($server->exist($_fd)) {
$server->push($_fd, "this is server onReceive");
}
}
$server->send($fd, 'receive: '.$data);
});
$server->start();
来源https://www.wenjiangs.com/doc/server-port
网友回复
为啥所有的照片分辨率提升工具都会修改照片上的图案细节?
js如何在浏览器中将webm视频的声音分离为单独音频?
微信小程序如何播放第三方域名url的mp4视频?
ai多模态大模型能实时识别视频中的手语为文字吗?
如何远程调试别人的chrome浏览器获取调试信息?
为啥js打开新网页window.open设置窗口宽高无效?
浏览器中js的navigator.mediaDevices.getDisplayMedia屏幕录像无法录制SpeechSynthesisUtterance产生的说话声音?
js中mediaRecorder如何录制window.speechSynthesis声音音频并下载?
python如何直接获取抖音短视频的音频文件url?
js在浏览器中如何使用MediaStream与MediaRecorder实现声音音频多轨道混流?