Я пытаюсь передать данные между сервером и клиентским компьютером с помощью моей программы. Я очень мало знаю о 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;
Это сериализуется в буфер и отправляется с использованием Winsock’s send()
метод.
Моя цель состоит в том, чтобы как-то интерпретировать это сообщение и извлечь данные в похожей структуре на сервере.
Это прямое соединение между клиентом и сервером.
Как бы я подошел к интерпретации этих данных на серверной части?
Буду ли я:
а) цикл вызова recv()
записать то, что я получаю в буфер, и начать работать над интерпретацией сообщения только когда recv()
больше нечего вернуть, и все отправленное сообщение теперь находится в буфере? Я также не уверен, что произойдет, если клиент продолжит отправлять сообщения. Скажем, второе сообщение придет только тогда, когда первое recv()
«D? Или будет recv()
продолжить возвращать вещи, пока клиент продолжает отправлять сообщения?
ИЛИ ЖЕ
б) Начать работать над интерпретацией этих сообщений, как только они придут, даже если прибыла только часть сообщения? Заголовок должен сказать, сколько еще я должен ожидать. (это кажется очень долгой и утомительной задачей для достижения)
Разве нет способа получить как целое сообщение, полученное в буфер, и как-то преобразовать его в структуру, чтобы я мог работать с данными?
Извините, если я кого-то перепутал, если что-то неясно, пожалуйста, скажите мне, и я обновлю вопрос
У вас довольно много вопросов, связанных в один.
Я думаю, что наиболее важный для вас ответ заключается в том, что когда вы вызываете прием по TCP-сокету, он не будет волшебным образом обрабатывать прием в целом. сообщение для тебя. Фактически, если вы думаете об этом, единственное, что гарантировано, это то, что вы будете получать данные на 8-битной границе. Вызов на получение блокируется, пока не будет доступен хотя бы один байт (возможно, больше), и он может вернуть пустой буфер, если сокет закрыт.
Вооружившись этим знанием, вы должны быть на пути к ответу на вопрос № 2: «Вы ждете, пока не будет получено целое сообщение, или продолжаете звонить, получите», и ответ заключается в том, что вам следует звонить в службу «Back-to-Back». И анализируйте входные буферы, поскольку они приходят для десериализации отдельных байтов в структуру данных, которая определяется вашим протоколом приложения.
Важно понимать, что наличие очень большого буфера чтения не гарантирует, что вы получите все сообщение за один вызов! Это действительно важно понять. Это означает, что ваш код должен работать в предположении, что вы можете получать всего 1 байт за раз и столько же данных, сколько размер буфера чтения. Таким образом, когда вы выбираете размер буфера чтения, вы должны выбрать разумное значение, основанное на MTU сети (что-то вроде 1500 байтов обычно является хорошим выбором). Каждый звонок recv()
точно скажет, сколько байтов было прочитано.
Как только вы начнете получать данные, скопируйте данные во временный буфер, и, когда у вас будет достаточно, чтобы проанализировать заголовок одного сообщения, декодируйте его и определите, получили ли вы все сообщение целиком, или есть еще ожидающие. когда вы получили сообщение целиком, передайте его в свое приложение. Все это должно работать несколько независимо от приложения
(принимающий код должен иметь возможность принимать данные как можно быстрее, буферизовать их, анализировать и затем передавать декодированные сообщения в приложение).