LINUX.ORG.RU

Читать вот такими кусками, но накапливать в отдельный буфер до разделителя и обрабатывать этот буфер когда он готов, а потом сбрасывать и накапливать заново

vertexua ★★★★★
()

Протокол дерьмово спроектирован, переделывай. Длина сообщения должна идти первой.

Deleted
()

А что за сокет? TCP, UDP, Unix Domain? Смотрю, выше люди предположили, что TCP, так? Тогда это давно известная проблема, когда хочется UDP, но чтобы надёжно как TCP. Существует подходящий протокол: SCTP, который как-то не очень распространён. (Или, может, широко используется, но в узких кругах. Но кто знает, может, завтра, вдруг, станет популярным.)

Но недавно наконец-то сделали именно то, чего все ждали: отдельные сообщения поверх TCP, а именно Kernel Connection Multiplexor:

The motivation for this is based on the observation that although TCP is byte stream transport protocol with no concept of message boundaries, a common use case is to implement a framed application layer protocol running over TCP.

А вообще-то выше уже намекнули, что существует простое, быстрое и портабельное решение: Type-length-value подход для протокола. Длина указывается, но на второй позиции после типа сообщения (заранее известной длины, например, 1-4 байта).

gag ★★★★★
()
Последнее исправление: gag (всего исправлений: 1)
Ответ на: комментарий от Deleted

У меня вопрос в том, что длина сообщения гонится перед сообщением потоком байт с динамической длинной, я её хочу получить отдельно от сообщения с помощью делиметра. Придётся делать fixed width.

Deleted
()
Ответ на: комментарий от gag

TCP, да. Мне нужны чистые TCP сокеты.

Deleted
()
Ответ на: комментарий от gag

Спасибо за type-length-value. Попробую запилить. Я просто только учусь проектировать свой протокол поверх сокетов. Лабы по распределенным вычислениям.

На данный момент я сделал какашку в виде динамическая_длина_сообщения->сообщение. Где сообщение - это json, который имеет различные поля, в том числе 'type'.

То есть выглядит как то так:

b'164\x04{"type": "message", "body": "\\u041f\\u0440\\u0438\\u0432\\u0435\\u0442, \\u0412\\u0430\\u0441\\u044f!", "from": "\\u041c\\u0430\\u0448\\u0430", "to": "\\u0412\\u0430\\u0441\\u044f"}'

Здесь b'\x04' - делиметр между длиной и сообщением.

Вот только в примере я где-то налажал с длиной сообщения, похоже.

Deleted
()
Последнее исправление: merhalak (всего исправлений: 4)

Возможно я не понял суть твоей боли, но что мешает читать данные используя select и накапливая их в буфере? Как только в буффере появился разделитель, эта часть буффера обзывается «сообщение» и парсится дальше.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

Моя боль в том, что я не знаю Python. Ну у меня ещё 4 дня есть. Ещё 2 раза переписать полностью успею.

Deleted
()
Ответ на: комментарий от Deleted

Да не, я понял, что затупил. Скорее всего сменю на фиксированные 2 байта с числом в hex формате и не буду трахать мозг. Этого мне хватит с головой. Или даже 4. Чтобы обожраться.

Deleted
()
Последнее исправление: merhalak (всего исправлений: 1)
Ответ на: комментарий от Deleted

В интернетах есть примеры, но все они, честно говоря, хреновые (полурабочие, странные etc.). Вот вырезка из реально работающего кода: https://www.refheap.com/123411. Должно работать если я ничего лишнего не грохнул. В примере делимитер - newline, так же можно переделать на \0.

Что необходимо понять, так это что Tornado — асинхронный сервер. Основная логика в методах dispatch_client и process_request. dispatch_client epoll'ом ждет пока в сокете не появится newline, после чего берет всю строку и вызывает на нее dispatch_client. Последний обрабатывает запрос, пишет ответ в сокет, и вызывает dispatch_client. И так по кругу.

unlog1c ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.