多端口混合协议
更多的信息,请参考Swoole增加监听的端口与多端口混合协议
为了使我们的主服务器能支持除HTTP
和WebSocket
外的更多协议,我们引入了Swoole
的多端口混合协议
特性,在LaravelS中称为Socket
。现在,可以很方便地在Laravel上构建TCP/UDP
应用。
创建
Socket
处理类,继承Hhxsv5\LaravelS\Swoole\Socket\{TcpSocket|UdpSocket|Http|WebSocket}
namespace App\Sockets;
use Hhxsv5\LaravelS\Swoole\Socket\TcpSocket;
use Swoole\Server;
class TestTcpSocket extends TcpSocket
{
public function onConnect(Server $server, $fd, $reactorId)
{
\Log::info('New TCP connection', [$fd]);
$server->send($fd, 'Welcome to LaravelS.');
}
public function onReceive(Server $server, $fd, $reactorId, $data)
{
\Log::info('Received data', [$fd, $data]);
$server->send($fd, 'LaravelS: ' . $data);
if ($data === "quit\r\n") {
$server->send($fd, 'LaravelS: bye' . PHP_EOL);
$server->close($fd);
}
}
public function onClose(Server $server, $fd, $reactorId)
{
\Log::info('Close TCP connection', [$fd]);
$server->send($fd, 'Goodbye');
}
}
这些连接和主服务器上的HTTP/WebSocket连接共享
Worker
进程,因此可以在这些事件回调中使用LaravelS提供的异步任务投递
、SwooleTable
、Laravel提供的组件如DB
、Eloquent
等。同时,如果需要使用该协议端口的Swoole\Server\Port
对象,只需要像如下代码一样访问Socket
类的成员swoolePort
即可。public function onReceive(Server $server, $fd, $reactorId, $data)
{
$port = $this->swoolePort; // 获得`Swoole\Server\Port`对象
}
namespace App\Http\Controllers;
class TestController extends Controller
{
public function test()
{
/**@var \Swoole\Http\Server|\Swoole\WebSocket\Server $swoole */
$swoole = app('swoole');
// $swoole->ports:遍历所有Port对象,https://wiki.swoole.com/#/server/properties?id=ports
$port = $swoole->ports[1]; // 获得`Swoole\Server\Port`对象,$port[0]是主服务器的端口
foreach ($port->connections as $fd) { // 遍历所有连接
// $swoole->send($fd, 'Send tcp message');
// if($swoole->isEstablished($fd)) {
// $swoole->push($fd, 'Send websocket message');
// }
}
}
}
注册套接字。
// 修改文件 config/laravels.php
// ...
'sockets' => [
[
'host' => '127.0.0.1',
'port' => 5291,
'type' => SWOOLE_SOCK_TCP,// 支持的嵌套字类型:https://wiki.swoole.com/#/consts?id=socket-%e7%b1%bb%e5%9e%8b
'settings' => [// Swoole可用的配置项:https://wiki.swoole.com/#/server/port?id=%e5%8f%af%e9%80%89%e5%8f%82%e6%95%b0
'open_eof_check' => true,
'package_eof' => "\r\n",
],
'handler' => \App\Sockets\TestTcpSocket::class,
'enable' => true, // 是否启用,默认为true
],
],
关于心跳配置,只能设置在
主服务器
上,不能配置在套接字
上,但套接字
会继承主服务器
的心跳配置。对于TCP协议,
dispatch_mode
选项设为1/3
时,底层会屏蔽onConnect
/onClose
事件,原因是这两种模式下无法保证onConnect
/onClose
/onReceive
的顺序。如果需要用到这两个事件,请将dispatch_mode
改为2/4/5
,参考。'swoole' => [
//...
'dispatch_mode' => 2,
//...
];
测试。
TCP:
telnet 127.0.0.1 5291
UDP:Linux下
echo "Hello LaravelS" > /dev/udp/127.0.0.1/5292
其他协议的注册示例。
- UDP
'sockets' => [
[
'host' => '0.0.0.0',
'port' => 5292,
'type' => SWOOLE_SOCK_UDP,
'settings' => [
'open_eof_check' => true,
'package_eof' => "\r\n",
],
'handler' => \App\Sockets\TestUdpSocket::class,
],
],
- Http
'sockets' => [
[
'host' => '0.0.0.0',
'port' => 5293,
'type' => SWOOLE_SOCK_TCP,
'settings' => [
'open_http_protocol' => true,
],
'handler' => \App\Sockets\TestHttp::class,
],
],
- WebSocket:主服务器必须
开启WebSocket
,即需要将websocket.enable
置为true
。
'sockets' => [
[
'host' => '0.0.0.0',
'port' => 5294,
'type' => SWOOLE_SOCK_TCP,
'settings' => [
'open_http_protocol' => true,
'open_websocket_protocol' => true,
],
'handler' => \App\Sockets\TestWebSocket::class,
],
],