Рубрики
Uncategorized

Реализация службы протокола TCP с несколькими процессами, изученная swoole4. X

Автор оригинала: David Wong.

Студенты, изучившие фреймворк workman, обнаружат, что суть workman заключается в использовании расширения сокетов PHP плюс расширения pcntl для реализации базовых сетевых сервисов и планирования нескольких процессов. Давайте обсудим, как использовать модуль сокета сопрограммы swool для реализации наших собственных служб TCP. Давайте напишем небольшой фрагмент тестового кода. Испытание. php-код выглядит следующим образом

$socket = new Co\Socket(AF_INET, SOCK_STREAM, 0);
$socket->bind('127.0.0.1', 9601);
$socket->listen(128);

go(function () use ($socket) {
    while(true) {
        $client = $socket->accept(-1);
        $data = $client->recv(64,10);
        var_dump('Recv:'.$data);
        $client->sendAll('reply at '.time());
        $client->close();
    }
});

Мы выполняем

php test.php

Создайте новую консоль CMD и имитируйте TCP-клиент с помощью telnet. Вы можете увидеть следующие результаты:

telnet 127.0.0.1 9601
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
asd
reply at 1559713416
Connection closed by foreign host

Вышесказанное показывает, что мы успешно установили простой TCP-сервер. И внимательные студенты обнаружат, что если у меня есть некоторые особенности поведения базы данных после recv, то мой TCP-сервер может принимать только ссылки и обрабатывать одну ссылку одновременно, а параллелизм близок к 1. Таким образом, мы можем внести небольшое улучшение, а именно:

$socket = new Co\Socket(AF_INET, SOCK_STREAM, 0);
$socket->bind('127.0.0.1', 9601);
$socket->listen(128);

go(function () use ($socket) {
    while(true) {
        $client = $socket->accept(-1);
        go(function () use ($client){
            $data = $client->recv(64,10);
            var_dump('Recv:'.$data);
            //It takes time to simulate the database. Suppose our database also uses the cooperation API.
            \co::sleep(1);
            $client->sendAll('reply at '.time());
            $client->close();
        });
    }
});

Мы используем протокол, чтобы поместить логику после принятия соединения в другой дополнительный протокол, чтобы наш TCP-сервер мог продолжать принимать соединение, что улучшает наш параллелизм. Однако в реальном программировании мы не можем достичь полного 100% API совместного программирования, и моя машина также является многоядерным процессором, так как я могу максимально использовать свой процессор в данный момент? Таким образом, мы можем построить сервер протокола TCP с несколькими процессами, используя характеристики повторного использования портов и процесс swool.

Процесс внедрения

Поскольку в этой главе инкапсуляция всего процесса не является нашей заботой, поэтому мы напрямую используем компоненты процесса, инкапсулированные easysool.

composer require easyswoole/component

Чтобы реализовать мой класс процесса, код выглядит следующим образом

use Co\Socket;
use EasySwoole\Component\Process\AbstractProcess;

class Server extends AbstractProcess
{
    protected function run($arg)
    {
        $socket = new Socket(AF_INET, SOCK_STREAM, 0);
        //The key is to allow reuse
        $socket->setOption(SOL_SOCKET,SO_REUSEPORT,true);
        $socket->setOption(SOL_SOCKET,SO_REUSEADDR,true);
        $socket->bind('127.0.0.1', 9601);
        $socket->listen(128);
        go(function () use ($socket) {
            while(true) {
                $client = $socket->accept(-1);
                go(function () use ($client){
                    $data = $client->recv(64,10);
                    var_dump('Recv:'.$data);
                    //It takes time to simulate the database. Suppose our database also uses the cooperation API.
                    \co::sleep(1);
                    $client->sendAll('reply at '.time());
                    $client->close();
                });
            }
        });
    }
}

В приведенном выше коде мы добавляем возможность разрешить мультиплексирование портов, в противном случае в многопроцессорном режиме это приведет к сбою прослушивания. Мы тестируем пять процессов в режиме cli.

for ($i = 1;$i < 5;$i++){
    $p = new Server("TcpServer.{$i}");
    $p->getProcess()->start();
}
//Main process to wait for recycle
while($ret = \Swoole\Process::wait()) {
    echo "PID={$ret['pid']}\n";
}

Таким образом, мы просто реализуем службу протокола TCP с несколькими процессами. Одним словом, способность к сотрудничеству swool 4. X по-прежнему очень сильна. Это позволяет Php реализовать высокопроизводительный TCP-сервис с наименьшими затратами, а не изучать новый язык. Если требуется более совершенный код, пожалуйста, обратитесь к коду проекта http://easyswoole.com/рамки. Если есть студенты, которым это нравится, вы можете нажать на звездочку, адрес GitHub HTTPS://Github.com/easy-tool…