Я знаю, как отправить текстовое сообщение через сокет в C, и я знаю, как отправить двоичные данные (файл изображения) через сокет.
Как создать одно сообщение, включающее текстовую часть, а затем двоичные данные? Например:
"messageId: 12, messageLength: 34
{image binary data}"
@RemyLebeau — HTTP может отправлять текст и изображение, но вы отправляете изображение в формате base64 (что составляет + 33% к размеру сообщения).
Если вам нужен HTTP, укажите это в заголовке. Вы можете отправить через сокет много вещей, которые нарушат протокол HTTP.
@н.м. Мне нужен чистый сокет TCP
Зачем тогда поднимать HTTP? Кстати, HTTP не заставляет вас использовать base64 для отправки изображений.
@н.м. в заголовке ничего про HTTP нет, это TCP. Я писал о HTTP, когда отвечал RemyLebeau.
Я упомянул HTTP просто как пример протокола, который может отправлять текст и двоичные файлы в одном сообщении.
Выберите протокол, который работает.
TLDR: memcpy и специальный символ-разделитель между текстовым заголовком и двоичными данными. Разделителем может быть символ конца строки (\n
).
char* CreateMessage(int messageId, size_t messageLength, char* binaryData, /*out*/ size_t* total)
{
char szHeader[100] = {0};
size_t headerLen = 0;
sprintf(szHeader, "messageId: %d, messageLength: %d\n", messageId, messageLength);
headerLen = strlen(szHeader);
total = headerLen + messageLength;
char* data = malloc(total);
memcpy(data, header, headerLen);
memcpy(data+headerLen, binaryData, messageLength);
return data;
}
И затем, когда вы хотите отправить некоторые данные:
size_t total = 0;
char* message = CreateMessage(12, 34, binaryData, &total);
send(s, message, total, 0);
free(message);
В качестве альтернативы, если вы используете TCP, нет причин, по которым вы не можете использовать два вызова отправки. Один для заголовка (с символом '\n'), а другой для двоичных данных. Получатель в любом случае должен обрабатывать сообщения, которые сегментируются и фрагментируются.
Не существует символа, который мог бы надежно различать «текст» и «двоичные данные». «текст» является подмножеством «двоичных данных».
@MartinJames - Правильно. Я хочу сказать, что он может легко комбинировать свой «текстовый» заголовок со своими «двоичными» данными, если использует соответствующий разделитель для обозначения конца текстовой строки.
TCP не знает, что такое «текст» или «сообщение». Он имеет дело с потоками байтов. Если у вас есть массив байтов, вы можете отправить его по TCP. Если у вас есть более одного массива, вы можете отправлять их по TCP один за другим, и результат будет неотличим от объединения всех этих массивов в один и отправки их в виде одного большого куска байтов.
Отправка байтов --- любых байтов --- по TCP не проблема. Проблема заключается в извлечении значимых частей («сообщений») из потока байтов. Это не имеет ничего общего с TCP, и все, что связано с тем, как вы определяете «сообщение» с точки зрения содержимого вашего потока, то есть вашего протокола.
Вы можете определить свой протокол, сказав, что «сообщение — это строка, заканчивающаяся символом новой строки», и это подходит для отправки текстовых сообщений, в которых нет встроенной новой строки. Это не будет работать для двоичных сообщений, потому что двоичный BLOB-объект, скорее всего, будет иметь встроенный символ новой строки.
Вы можете определить сообщение, сказав, что «сообщение представляет собой 4-байтовую величину, интерпретируемую как беззнаковое целое число сетевого порядка, за которым следует такое количество байтов полезной нагрузки». Это нормально как для текстовых, так и для бинарных сообщений, но немного неудобно для текста, потому что вам нужно вычислить и отправить длину каждой строки.
Вы можете сказать: «Мой поток содержит строго чередующиеся текстовые и бинарные сообщения, текст завершается символом новой строки, а бинарному предшествует его длина», и это тоже будет работать, хотя вы не можете отправлять два текстовых или два бинарных сообщения подряд.
Вы можете сказать: «Мой поток содержит ровно два сообщения, текст, заканчивающийся новой строкой, а затем двоичный файл». Длина не передается явно, конец потока — это конец двоичного сообщения.
Видишь, это все есть в твоем протоколе. TCP не волнует. Все, что он знает, это байты.
Я скучал по чтению от вас. +1
Почти идеально :)
Вы уже знаете, как отправлять текст, и как отправлять двоичные файлы, так что же вам мешает совместить их? Сначала отправьте текст, а затем отправьте двоичный файл. TCP не имеет понятия о сообщениях, поэтому ему все равно, сколько вы отправляете. Ваш протокол диктует, что содержит сообщение. Взгляните, например, на протокол HTTP. Он использует смешанные текстовые + двоичные сообщения.