2014-11-01 2 views
2

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

До сих пор сообщение о моем собственном упрощенном протоколе определяется следующим образом:

int _header_signature; 
int _offset_a; 
int _offset_b; 
int _size_a; 
int _size_b; 
wchar_t stuff[_size_a]; 
wchar_t stuff2[_size_b]; 
int _footer_signature; 

Это получает сериализовать на буфер и получает отправить с помощью метода send() Winsock в.

Моя цель - как-то интерпретировать это сообщение и извлекать данные в подобной структуре на серверной машине. Это соединение «один к одному» между клиентом и сервером.

Как я мог бы интерпретировать эти данные на серверной части?

я бы:

а) Цикл вызова recv() писать то, что я получаю в буфер, и начать работать на интерпретируют сообщение только тогда, когдаrecv() не имеет ничего больше, чтобы вернуться, и все сообщения, отправленного в настоящее время на буфер? Я также не уверен, что произойдет, если клиент продолжит отправлять сообщения. Будет ли второе сообщение, скажем, прибыть только тогда, когда первый закончил быть recv() 'd? Или будет recv() продолжать возвращать вещи, пока клиент продолжает отправлять сообщения?

ИЛИ

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

Не существует способа получить как все сообщение, полученное в буфер, и каким-то образом передать его в структуру, чтобы я мог работать с данными?

Я извиняюсь, если я спутать кого угодно, если что-то непонятно, пожалуйста, скажите мне, и я буду обновлять этот вопрос

ответ

2

У вас есть немало вопросов в одном комплекте.

Я думаю, что наиболее важным для вас является то, что когда вы вызываете получать по сокету TCP, он не будет магически обрабатывать получение целого сообщения для вас. На самом деле, если вы думаете об этом, единственное, что гарантировано, это то, что вы получите данные на 8-битной границе. Вызов для приема блокируется до тех пор, пока не будет доступно хотя бы один байт (возможно, больше), и он может вернуть пустой буфер, если сокет закрыт.

Вооружившись этим знанием, вы должны быть на пути к ответе на вопрос № 2: «Подождите, пока не будет получено целое сообщение или не получит вызов», и ответ заключается в том, что вы должны называть прием обратно назад , И проанализируйте входные буферы, поскольку они приходят к десериализации отдельных байтов в структуру данных, которую диктует ваш прикладной протокол.

Важно помнить, что наличие очень большого буфера чтения не гарантирует, что вы получите все сообщение за один звонок! Это действительно важно понять. Это означает, что ваш код должен работать в предположении, что вы можете получать всего 1 байт за раз и столько же данных, сколько размер вашего буфера чтения.Таким образом, когда вы определяете размер буфера чтения, вы должны выбрать разумное значение, основанное на MTU сети (примерно 1500 байтов, как правило, являются хорошим выбором). Каждый звонок до recv() точно скажет, сколько байтов было действительно прочитано.

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

+0

Так что вы говорите мне (если буфер, который recv() пишет меньше моего сообщения), мне нужно вызвать recv() получить небольшую часть сообщения, использовать некоторый код для интерпретации столько же, сколько , call recv() снова получает еще одну небольшую часть сообщения и интерпретирует столько, сколько получено, и так далее и так далее? –

+0

Да, на самом деле не имеет значения, насколько большой буфер вы используете, он может не заполниться одним вызовом recv(). –