2012-02-26 2 views
1

Я работаю над проектом клиент-сервер и должен реализовать логику, где мне нужно проверить, получил ли я последние данные по соединению сокетов TCP, прежде чем продолжить. Чтобы убедиться, что я получил все данные, я планирую поместить флаг в последний отправленный пакет. У меня было два варианта, как показано ниже, а также связанная с этим проблема.Заполнение данных по TCP

i. Используйте структуру, как показано ниже, и заполните vst_pad для последнего отправленного пакета и проверьте его на стороне recv для его присутствия. Преимущество над вторым вариантом заключается в том, что я не имею, чтобы удалить флаг из фактических данных перед записью на file.Just проверить первый член структуры

typedef struct 
    { 
    /* String holding padding for last packet when socket is changed */ 
    char vst_pad[10]; 
    /* Pointer to data being transmitted */ 
    char *vst_data; 
    //unsigned char vst_data[1]; 
    } st_packetData; 

Проблема в том, я должен сериализовать-структуру на каждый отправляемый звонок. Кроме того, я не уверен, получу ли я всю структуру через TCP в одном вызове recv и поэтому должен добавить логику/накладные расходы, чтобы проверять это каждый раз. Я реализовал это до сих пор, но позже понял, что потоковый TCP-протокол не может гарантировать возврат всей структуры в один вызов.

ii. Используйте функцию strncat, чтобы добавить этот флаг в конец к последним отправляемым данным.

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

Это приложение предназначено для больших объемов передачи данных и поэтому позволяет добавлять минимальные накладные расходы при каждом вызове send/recv/read/write. Было бы очень полезно знать, есть ли лучший вариант, чем предыдущие два или любой другой вариант проверки получения последнего пакета. Программа многопоточная.

Редактировать: Я не знаю общий размер файла, который я собираюсь отправить, но я отправляю фиксированный объем данных. Это fgets читается до тех пор, пока размер не будет указан -1 или пока не встретится новая строка.

ответ

2

Знаете ли вы размер данных заранее, и это требование, чтобы вы реализовали флаг конца сообщения?

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

Таким образом, вы анализируете первые 4 байта, вычисляете размер, а затем продолжаете вызывать recv, пока не получите столько данных.

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

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

Использование заголовка фиксированного размера и известное значение размера облегчат эту проблему.

+0

Алан: Я не знаю общий размер файла, который я собираюсь отправить, но я отправляю фиксированный объем данных. То есть, fgets читается до указанного размера -1 или до тех пор, пока не встретится новая строка. Я могу использовать strlen в буфере, чтобы узнать фактическую длину данных. – user369823

+1

и, конечно же, вам нужно разобрать эти 4 байта, которые могут быть отправлены в 4 разных вызовах recv. – bew

+0

@Alan: Thnx для ответов до сих пор. Я частично реализовал то, что вы предложили, но я хотел бы знать, как именно я знаю размер, который должен быть помещен в заголовок. Я читаю исправление chuck данных из файла, используя fgets и передавая тот же размер размера. Но как его TCP я точно не знаю размер данных, отправленных до проверки ответа на вызов. Я немного запутался в этом. Псевдокод будет очень полезен ... – user369823

0

Не могли бы вы использовать библиотеку связи с открытым исходным кодом, написанную на C#? Если да, то сделайте заказ networkComms.net.

+0

Вопрос отмечен C, и это приложение для обмена сообщениями на низком уровне TCP. – Alan

+0

MarcF: Спасибо за ответ. Как указал Алан, я снова кодирую в C.Thnks. – user369823

1

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

На приемном конце, просто read короткий и преобразовать обратно в порядок пребывания (как это позволит использовать различные процессоры на более позднем состоянии. Вы можете read остальные данные.

+0

Эд: Спасибо за ответ. Я уже отправляю фиксированный объем данных, но не уверен, что выборка данных из файла имеет тот же размер или меньше. Функция fgets и send имеет одинаковый объем данных в своем вызове. Вы предлагаете использовать функцию типа strlen для определения фактической длины данных, которая должна быть назначена для короткой переменной? – user369823

0

Если это истинно последние данные, посылаемые вашим приложением, используйте shutdown(socket, SHUT_WR); на стороне отправителя.

Это установит флаг FIN TCP, который сигнализирует о том, что Sender-> поток приемника закончена. приемник будет знать это, потому что его RECV() будет возвращать 0 (точно так же, как условие EOF), когда все получено. Приемник все равно может отправлять данные позже, а отправитель ca n все еще прослушивает их, но он не может отправлять больше, используя это соединение.

+0

BatchyX. По дизайну я буду нуждаться в том же соединении позже. Я не знаю, будет ли такое же соединение использоваться позже или нет. Это зависит от выбора пользователей. – user369823

1

В таких случаях обычно блокировать данные в куски и предоставлять заголовок блока, а также трейлер. Заголовок содержит длину данных в куске и, таким образом, эксперт знает, когда ожидается трейлер - все, что ему нужно сделать, это count rx bytes, а затем проверить действительный трейлер. Эти куски позволяют передавать большие данные без огромных буферов с обоих концов.

Нет ничего сложного в том, чтобы добавить байт статуса в заголовок, который может идентифицировать последний фрагмент.

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

+0

Мартин: Спасибо за быстрый ответ. Я могу добавить короткие, как предложил г-н Эд внизу в структуре, чтобы указать длину данных, а затем петлю на стороне recv до тех пор, пока не будет получен этот объем данных. Я бы попытался сначала выполните одно и то же. – user369823