2009-10-21 4 views
4

Мне нужно отправить данные сетки через TCP с одного компьютера на другой ... Эти ячейки могут быть довольно большими. Мне сложно подумать о том, какой лучший способ отправить их через TCP будет, поскольку я мало знаю о сетевом программировании.Отправка больших кусков данных через Boost TCP?

Вот моя основная структура класса, что мне нужно, чтобы вписаться в буфер для отправки через TCP:

class PrimitiveCollection 
{ 
    std::vector<Primitive*> primitives; 
}; 

class Primitive 
{ 
    PRIMTYPES primType; // PRIMTYPES is just an enum with values for fan, strip, etc... 
    unsigned int numVertices; 
    std::vector<Vertex*> vertices; 
}; 


class Vertex 
{ 
    float X; 
    float Y; 
    float Z; 
    float XNormal; 
    float ZNormal; 
}; 

Я использую библиотеку Boost, и их TCP вещи ... это довольно простой в использовании , Вы можете просто заполнить буфер и отправить его через TCP.
Однако, конечно, этот буфер может быть только настолько большим, и у меня может быть до 2 мегабайт данных для отправки.

Так что было бы лучшим способом получить вышеуказанную структуру класса в буферах, необходимых и отправленных по сети? Мне также нужно было бы десериализовать на получающем конце.

Любые указания в этом отношении будут высоко оценены.

EDIT: Я понимаю, что это еще одна проблема, которая не является специфической для Boost ... Это больше проблема с перекосом данных и их отправкой. Однако мне все еще интересно узнать, есть ли у Boost что-нибудь, что может немного отвлечь его.

+2

Ну, независимо от того, какой API вы используете, один простой способ - сначала отправить небольшой 4 байтовый hedaer, описывающий, насколько большой будет набор данных, а затем просто продолжать отправлять данные, пока вы не закончите. На самом деле нет предела. Вы также можете сжать данные перед отправкой, в зависимости от ваших вычислительных потребностей. Многое зависит от конкретной проблемы. – BobbyShaftoe

ответ

2

Вы пробовали его с помощью TCP-протокола Boost? Я не понимаю, почему 2 МБ будет проблемой для передачи. Я предполагаю, что мы говорим о LAN, работающей со скоростью 100 Мбит/с или 1 Гбит/с, компьютере с большим количеством ОЗУ и не нужно иметь время отклика 20 мс? Если ваша цель - просто получить все 2 МБ с одного компьютера на другой, просто отправьте его, TCP будет обрабатывать его для вас.

У меня есть средство проверки задержек TCP, которое я написал с помощью Boost, который пытается отправить буферы разных размеров, я регулярно проверяю до 20 МБ, и они, кажется, проходят без проблем.

Я предполагаю, что я пытаюсь сказать, не тратить время на разработку решения, если вы не знаете, у вас есть проблема :-)

--------- Решение реализации - ------

Теперь, когда у меня было несколько минут на моих руках, я прошел и сделал быструю реализацию того, что вы говорили о: https://github.com/teeks99/data-chunker есть три большие части:

в сериализатор/десериализатор, у boost есть свои, но это не намного лучше, чем сворачивать ваши собственные, поэтому я и сделал.

Отправитель - Подключение к приемнику через TCP и отправляет данные

приемник - ожидает соединений от отправителя и распаковывает данные, которые он принимает.

Я включил .exe (s) в zip, запустил Sender.exe/Receiver.exe --help, чтобы просмотреть параметры, или просто взглянуть на главную.

Более подробное объяснение: Откройте два командных запроса и перейдите в DataChunker \ Debug в обоих из них. Запустите Receiver.exe в одном из Запустите Sender.exe в другом (возможно на другом компьютере, и в этом случае добавьте -remote-host = IP.ADD.RE.SS после имени исполняемого файла, если хотите попробуйте отправить более одного раза и --num-send = 10 отправить десять раз). Посмотрев на код, вы можете видеть, что происходит, создавая концы приемника и отправителя сокета TCP в функциях respecitve main(). Отправитель создает новый PrimitiveCollection и заполняет его некоторыми примерами данных, затем сериализует и отправляет его ... получатель десериализует данные в новый PrimitiveCollection, после чего примитивная коллекция может быть использована кем-то другим, но я просто написал на консоль, чтобы это было сделано.

Редактировать: Переместить пример в github.

+0

Да, я думаю, я пытаюсь использовать Boost TCP как можно более эффективно ... похоже, не так много примеров, использующих его эффективно. – Polaris878

+0

загрузка не работает - можете ли вы добавить новую ссылку –

+0

@ teeks99, у вас все еще есть пример? Было бы здорово, если бы вы обновили мертвую ссылку, спасибо. – Katu

2

без ничего фантазии, от того, что я помню, в моей сети класса:

  • Отправить сообщение для приемника, спрашивая, что размер порции данных, он может обрабатывать
  • Возьмите минимум, что и ваши собственные отправки возможности , то ответ сказал:
    • Какой размер вы будете посылать, сколько вы будете посылать
  • После вас г et, просто отправьте каждый кусок. Вам нужно подождать ответа «Хорошо», поэтому вы знаете, что не тратите время на отправку клиенту, которого там нет. Это также хорошее время для отправки клиентом сообщения «Я отменяю» вместо «ОК».
  • Отправлять, пока на все пакеты не ответил «ОК»
  • Данные передаются.

Это работает, потому что TCP гарантирует доставку в порядке. UDP потребует номера пакетов (для заказа).

Сжатие - это то же самое, за исключением того, что вы отправляете сжатые данные. (Данные - это данные, все зависит от того, как вы это интерпретируете). Просто убедитесь, что вы сообщаете, как сжимаются данные.

Как для примера, все, что я мог выкопать, было this page и это old question. Я думаю, что вы делаете хорошо в тандеме с Boost.Serialization.

2

Я хотел бы добавить еще один момент, чтобы рассмотреть - настройку размера буфера TCP-сокета, чтобы в какой-то мере увеличить производительность сокетов.

Есть утилита Iperf, которая позволяет протестировать скорость обмена через сокет TCP. Я провел в Windows несколько тестов в локальной сети 100 Мбит.С размером экрана TCP по умолчанию 8Kb скорость составляет 89 Мбит/с и с размером окна TCP в размере 64 Кбит скорость составляет 94 Мбит/с.

-1

В дополнение к тому, как распределять и передавать данные, еще одна проблема, которую вы должны учитывать, это различия в платформе. Если оба компьютера имеют одинаковую архитектуру, а код, работающий с обеих сторон, является той же версией одного и того же компилятора, то вам, вероятно, удастся просто сбросить структуру необработанной памяти по сети и заставить ее работать с другой боковая сторона. Если все не то же самое, вы можете столкнуться с проблемами с контентом, заполнением структуры, выравниванием полей и т. Д.

В общем, полезно определить сетевой формат данных отдельно от вашего представления в памяти , Этот формат может быть двоичным, и в этом случае числовые значения должны быть преобразованы в стандартные формы (в основном, изменение сущности в «порядок сети», что является широковещательным), или оно может быть текстовым. Многие сетевые протоколы выбирают текст, поскольку устраняют множество проблем с форматированием и облегчают отладку. Лично мне очень нравится JSON. Это не слишком многословно, есть хорошие библиотеки, доступные для каждого языка программирования, и людям очень легко читать и понимать.

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

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

На стороне приема вы просто отменяете процесс, декодируя сетевой формат в соответствующий формат в памяти.

Моя рекомендация для вашего случая - использовать JSON. 2 МБ не так много данных, поэтому накладные расходы на генерацию и синтаксический анализ не будут большими, и вы можете легко представить свою структуру данных непосредственно в JSON. Полученный текст будет самограничиваться, легко читаться, легко переноситься и легко разбираться в памяти на стороне назначения.

+0

Ничего себе, здесь много информации. Я собирался поддержать вас для комментария, чтобы отделить сериализацию протокола от представления в памяти, но ... JSON, для чего значительная доля научных данных? Нет, мужик. – Tom

+0

Для 2 МБ нет смысла делать что-либо еще. Таким образом, он расширяется до 5 или 6 МБ, так что? Вы все еще говорите крошечную долю секунды, чтобы передать его. JSON проще и безопаснее, чем удалять двоичные форматы. Во многих случаях прокладка его через компрессор/декомпрессор приведет к меньшему размеру переноса, чем бинарный формат. Если бы мы говорили о больших объемах данных, я бы дал совсем другой ответ, но для этого упростись. – divegeek

Смежные вопросы