кэшировать неиспользуемые данные для каждого соединения? - PullRequest
0 голосов
/ 23 февраля 2012

Я пишу программу на C, состоящую из одного потока диспетчера и N рабочего потока, ответственность за который описана ниже:

поток диспетчера: прослушивание порта TCP;делать epoll_wait () повторно на этом порту;когда соединение установлено, примите его и передайте новый файловый дескриптор (то есть, что возвращает функция «accept») одному из рабочих потоков N;

рабочий поток: при каждом новом подключении повторяйте чтение до тех пор, пока не будет данныхполучено;использование всех данных, полученных в качестве параметра, для вызова функции декодирования, которая будет декодировать данные в структуру сообщения (т.е. сообщение RTSP);

, что мне интересно, так это то, что если данные, прочитанные рабочим потоком, являются неполными,я должен кешировать его, что означает, что я должен поддерживать глобальный список для кеширования неиспользуемых данных (т.е. полученных, но не полных сообщений, поэтому еще не использованных) для каждого соединения?

Ответы [ 4 ]

0 голосов
/ 23 февраля 2012

Глобальный список? Зачем вам такая вещь? Параметр buffer / buffer-array / buffer-connectedList / buffer-what должен быть членом объекта сокета или ссылаться на него / из него. Если данные должны быть проанализированы и заблокированы в какой-то блок прикладного протокола, то да, «оставшиеся» данные должны быть изолированы, чтобы они могли стать частью следующего APU. Либо скопируйте его, либо разрешите каждому буферу иметь «начальный индекс», который не обязательно должен быть 0.

0 голосов
/ 23 февраля 2012

Необходимость кэширования данных зависит от длины данных, количества подключений и объема памяти.Например, предположим, что мы используем HTTP, нормальный заголовок HTTP должен быть меньше 4096 байт, если клиент использует метод POST, мы можем проанализировать «Content-Length», если Content-Length слишком велик, мы можем кэшировать данные публикации ввременные файлы.

0 голосов
/ 23 февраля 2012

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

Если вы используете работника для обработки нескольких сокетов неблокирующим образом, вы можете использовать этот подход:

  1. Начать чтение данных в заранее определенном размере буфера. (Попробуйте сопоставить размер буфера с максимально возможной длиной сообщения, это сохранит ваши копии).

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

  3. Если сообщение полностью прочитано, обработайте его, в противном случае сохраните буфер и количество байтов для чтения для этого сообщения и повторите цикл через сокеты (ваше хранилище).

  4. При следующей обработке того же сокета вы проверите, есть ли у вас в данный момент частичное сообщение, и продолжите чтение в тот же буфер из того места, которое вы закончили в прошлый раз. Вам нужно прочитать здесь следующие x байтов, и вы должны быть готовы иметь меньше, чем вы ожидаете. Здесь вы также можете добавить оптимизацию, считывая все, что у вас есть (оставлено в буфере) на этом сокете за один раз (не только следующие x оставшихся байтов, сохраняя некоторые системные вызовы). Если вы сделаете это, вам нужно будет использовать векторы (readv () или аналогичные).

Если вы обходитесь без оптимизации, с ней довольно просто справиться.

0 голосов
/ 23 февраля 2012

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

  1. Либо сбросьте сообщение и запросите повторную передачу (что является простым случаем)
  2. Отследите пакет, выясните, где он был обрезан, и повторите передачу только оставшейся части сообщения.

Надеюсь, это поможет.

...