#c #python #tcp #protocol-buffers
#c #python #tcp #протокол-буферы
Вопрос:
В настоящее время я пытаюсь реализовать протокол (T) LV, который будет использоваться поверх TCP. Очень ранняя версия этого протокола была создана путем простой отправки одного сообщения на пару send-recv. (т.е. send(«сообщение для передачи» — recv(… )). Это действительно плохо с точки зрения пропускной способности — я думаю, потому что я отправляю действительно маленькие пакеты. Итак, теперь я пытаюсь переключиться на протокол LV, отправляя сразу несколько сообщений, разделенных только их соответствующей длиной (теперь я использую буферы протокола для сериализации моих данных).
Теперь у меня есть два вопроса:
-
В python я отправляю, выполняя
sock.send(struct.pack("<H", len(gtMessage.SerializeToString())))
sock.send(gtMessage.SerializeToString())
Если бы я сейчас поместил это в цикл и отправил несколько таких сообщений, я бы в конечном итоге столкнулся со своей старой проблемой, насколько я понимаю. Могу ли я как-то связать строку для отправки вместе?
- В C я получаю сначала длину сообщения, а затем считываю количество байтов, указанное в поле длины.
Лучше ли с точки зрения производительности сначала прочитать все из TCP, а затем проанализировать его, или я могу прочитать одно сообщение, затем проанализировать его и только затем прочитать следующий бит из провода?
Редактировать: итак, после проведения дополнительных исследований я бы перефразировал первый вопрос следующим образом:
Является
sock.send("somestring")
sock.send("somestring")
то же, что
sock.send("somestring" "somestring")
?
Ответ №1:
Выполнение двух отправок подряд может привести к отправке двух фактических пакетов, что не так уж и здорово. Чтобы исправить это, вы можете объединить две части самостоятельно или использовать writev
(он же «собрать запись») или TCP_CORK при первой отправке, чтобы предотвратить ее самостоятельное превращение в пакет.
Что касается принимающей стороны, вы должны получить большой блок (столько, сколько сможете, до некоторого разумного предела, скажем, пару мегабайт или что-то в этом роде), а затем проанализировать его. Не пытайтесь получить только один или два байта для размера, а затем выполнить еще один прием после этого — это неэффективно, и вы все равно можете получить «короткие чтения», если отправленное сообщение было фрагментировано.