swoole--协程TCP服务器

2021-05-23

支持TCP和unixSocket类型
动态创建销毁,在运行时可以动态监听端口,也可以动态关闭服务器
处理连接的过程是完全同步的,程序可以顺序处理Connect、Receive、Close事件

use Swoole\Coroutine;
use Swoole\Coroutine\Server;
use Swoole\Coroutine\Server\Connection;

// 创建一个监听$host,$port的服务,$ssl为true时启用ssl,$reuse_port为true启动端口重用
// $host支持:IPv4地址(0.0.0.0/127.0.0.1)、IPv6地址(::/::1)、UnixSocket地址(unix:/tmp/test.sock)
$server = new Server($host, $port = 0, $ssl = false, $reuse_port = false);

// 设置参数数组,与Swoole\Coroutine\Socket->setProtocol方法接受的配置项完全一致
$server->set($options);
// 长度协议
[
  'open_length_check'     => true,
  'package_max_length'    => 1024 * 1024,
  'package_length_type'   => 'N',
  'package_length_offset' => 0,
  'package_body_offset'   => 4,
];
// SSL证书设置
[
  'ssl_cert_file' => dirname(__DIR__) . '/ssl/server.crt',
  'ssl_key_file'  => dirname(__DIR__) . '/ssl/server.key',
];


// 服务器在Accept(建立连接) 成功后,会自动创建协程并执行$fn;$fn是在新的子协程空间内执行,因此在函数内无需再次创建协程
// $fn接受一个参数,类型为Swoole\Coroutine\Server\Connection对象;
// 可以使用Coroutine\Server\Connection::exportSocket()得到当前连接的Socket对象
$server->handle($fn = function (Connection $conn) {
    while (true) {

        // 接收数据,如果设置了协议处理,将每次返回完整的包
        $data = $conn->recv(float $timeout = 0);

        if ($data === '' || $data === false) {
            $errCode = swoole_last_error();
            $errMsg = socket_strerror($errCode);
            echo "errCode: {$errCode}, errMsg: {$errMsg}\n";

            // 关闭连接
            $conn->close();
            break;
        }

        // get客户端发送数据$data
        $conn->send(string $data);

    	// 得到当前连接的Swoole\Coroutine\Socket对象。可调用更多底层的方法
    	$data = $conn->exportSocket();

        Coroutine::sleep(1);
    }
});


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

// 终止服务器
$server->shutdown();
{/if}