Использование функций пользовательского протокола 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 ++;
}
Запустите код напрямую, и всё будет работать идеально!
Обратите внимание на ссылку для просмотра полного примера.
Начиная с версии 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 )