1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/phpArtist-swoole-start

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
05.Swoole的自定义协议功能的使用.md 12 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 26.11.2024 04:51 cb930a5

Использование функций пользовательского протокола Swoole

Содержание:

  • Почему нужно предоставлять пользовательский протокол?
  • Протокол типа EOF-маркера.
  • Тип протокола с фиксированным заголовком пакета.
  • Специальная статья: HTTP-протокол — встроенный HTTP_server в Swoole.

Описание среды: Операционная система: Ubuntu 14.04 (включая инструкции по установке CentOS 6.5). Версия PHP: PHP-5.5.10. Версия Swoole: 1.7.8-alpha.

Почему нужно предоставлять пользовательский протокол

Друзья, знакомые с TCP-коммуникацией, знают, что TCP — это потоковый протокол. Данные, отправленные клиентом на сервер, могут быть получены сервером не сразу целиком; данные, отправленные несколькими частями, могут быть полностью получены сервером за один раз. В реальных приложениях мы хотим, чтобы сервер мог получать целый фрагмент данных, не слишком большой и не слишком маленький. Традиционный TCP-сервер обычно требует, чтобы программист поддерживал область кэширования, сначала помещал полученные данные в область кэширования и затем использовал заранее определённый протокол для разделения начала, длины и конца целого фрагмента данных и передавал целый фрагмент данных в логическую часть для обработки. Это функция пользовательского протокола.

В Swoole уже реализован буфер данных и несколько часто используемых протоколов, данные разделены на уровне ядра, и гарантируется, что в функции обратного вызова onReceive можно получить один или несколько целых фрагментов данных. Размер буфера данных можно контролировать с помощью параметра конфигурации package_max_length. Ниже я объясню, как использовать эти встроенные протоколы.

Протокол типа EOF-маркера

Первый часто используемый протокол — это протокол типа EOF-маркера. Содержание протокола заключается в том, чтобы определить символ или строку, которые никогда не появятся в обычных данных, и использовать их для обозначения конца целого фрагмента данных. Таким образом, когда обнаруживается этот конец, можно определить, что предыдущие данные закончились, и можно начать получать новый фрагмент данных.

В Swoole вы можете включить его с помощью параметров конфигурации open_eof_check и package_eof. Среди них open_eof_check указывает, включён ли детектор EOF, а package_eof указывает конкретный маркер EOF. С этими двумя параметрами ядро Swoole автоматически кэширует и разделяет полученные пакеты данных на основе маркера EOF. Пример кода:

$this->serv->set(array(
    'package_max_length' => 8192,
    'open_eof_check'=> true,
    'package_eof' => "\r\n"
));

Таким образом, Swoole активировал анализ протокола типа EOF-маркера. Давайте проверим эффект: Серверная сторона:

// Server
public function onReceive( swoole_server $serv, $fd, $from_id, $data ) {
    echo "Get Message From Client {$fd}:{$data}\n";
}

Клиентская сторона:

$msg_eof = "This is a Msg\r\n";

$i = 0;
while( $i < 100 ) {
    $this->client->send( $msg_eof );
    $i ++;
}

Затем запустите его, и вы обнаружите: подождите, почему все ещё получено так много данных сразу!

Это связано с тем, что Swoole использует не метод обхода для идентификации, а просто проверяет, является ли конец каждого полученного фрагмента данных определённым маркером EOF. Поэтому после включения детектора EOF в onReceive всё ещё возможно получение нескольких пакетов данных одновременно.

Что делать? Хотя это несколько пакетов данных, на самом деле они представляют собой N целых фрагментов данных, поэтому вам нужно только разделить каждый пакет на основе EOF и обработать их один за другим. Изменённый код на стороне сервера:

public function onReceive( swoole_server $serv, $fd, $from_id, $data ) {
    $data_list = explode("\r\n", $data);
    foreach ($data_list as $msg) {
        if( !empty($msg) ) {
            echo "Get Message From Client {$fd}:{$msg}\n";
        }
        
    }
}

Запустите снова, готово! Полный пример можно посмотреть здесь. Кроме того, если вы беспокоитесь о том, что выполнение нескольких фрагментов данных займёт слишком много времени, вы можете попробовать передать данные и fd в процесс Task. Как переслать, пожалуйста, попробуйте реализовать сами. Настройка параметров для анализа протокола фиксированной длины заголовка пакета

Можно включить функцию анализа протокола фиксированной длины заголовка пакета, установив опцию open_length_check. Кроме того, есть три параметра конфигурации: package_length_offset, package_body_offset и package_length_type, которые используются для управления функцией анализа. [package_length_offset] определяет, с какого байта в заголовке пакета начинается поле длины. [package_body_offset] задаёт длину заголовка пакета. [package_length_type] определяет тип поля длины.

Конкретные настройки следующие:

$this->serv->set(array(
    'package_max_length' => 8192,
    'open_length_check'=> true,
    'package_length_offset' => 0,
    'package_body_offset' => 4,
    'package_length_type' => 'N'
));

Для получения более подробной информации о том, как настроить эти параметры, обратитесь к документации.

OK, не будем больше говорить об этом, давайте сразу перейдём к примеру:

Серверная часть:

public function onReceive( swoole_server $serv, $fd, $from_id, $data ) {
    $length = unpack("N" , $data)[1];
    echo "Length = {$length}\n";
    $msg = substr($data,-$length);
    echo "Get Message From Client {$fd}:{$msg}\n";
}

Клиентская часть:

$msg_length = pack("N" , strlen($msg_normal) ). $msg_normal;

$i = 0;
while( $i < 100 ) {
    $this->client->send( $msg_length );
    $i ++;
}

Запустите код напрямую, и всё будет работать идеально!

Обратите внимание на ссылку для просмотра полного примера.

4. Специальная статья: HTTP-протокол — встроенный http_server Swoole

Начиная с версии Swoole 1.7.7-stable, Swoole внутренне упаковывает и реализует HTTP-сервер. Да, вы правильно поняли, вам больше не нужно кэшировать и анализировать HTTP-протоколы на уровне PHP, Swoole теперь имеет встроенный HTTP-сервер. Чтобы создать объект swoole_http_server, используйте следующий код:

$http = new swoole_http_server("127.0.0.1", 9501);
$http->on('request', function (swoole_http_request $request, swoole_http_response $response) {
    $response->end("<h1>Hello Swoole.</h1>");
});
$http->start();

Вам нужно только создать объект swoole_http_server и установить функцию обратного вызова onRequest, чтобы реализовать HTTP-сервер. В функции обратного вызова есть два параметра. Параметр $request содержит информацию о запросе от клиента, включая заголовок HTTP-запроса, информацию о сервере, связанную с HTTP-запросом, параметры GET и POST, а также файлы cookie, связанные с HTTP-запросами. Параметр $response используется для отправки данных клиенту, через этот параметр можно установить информацию заголовка HTTP-ответа, файлы cookie и статус.

Кроме того, swoole_http_server также предоставляет функцию WebSocket. Чтобы использовать эту функцию, необходимо установить функцию обратного вызова onMessage следующим образом:

$http_server->on('message', function(swoole_http_request $request, swoole_http_response $response) {
    echo $request->message;
    $response->message(json_encode(array("data1", "data2")));
})

Вы можете получить сообщение WebSocket, отправленное с помощью $request->message, и ответить на сообщение с помощью $response->message().

Обратите внимание, что автор делает небольшую рекламу в конце статьи, говоря о том, что он успешно перенёс Yaf-фреймворк на swoole_http_server. Он утверждает, что производительность swoole-yaf значительно превосходит производительность nginx + php-fpm + yaf. Автор также говорит, что продолжит улучшать проект и стремиться к его использованию в реальных проектах.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/phpArtist-swoole-start.git
git@api.gitlife.ru:oschina-mirror/phpArtist-swoole-start.git
oschina-mirror
phpArtist-swoole-start
phpArtist-swoole-start
master