Отправить другие типы данных в winsock2

Функция отправки в winsock2 принимает только указатели на символы. Как мне отправить через него целые числа или объекты?


person Pilpel    schedule 22.08.2011    source источник


Ответы (3)


const char *buf, который вам нужно передать send() функции в качестве аргумента, это просто указатель на массив байтов. Вам нужно преобразовать целые числа в байты:

const int MAX_BUF_SIZE = 1024;
int int_data = 4;
const char *str_data = "test";

char *buf = (char*) malloc(MAX_BUF_SIZE);
char *p = buf;

memcpy(&int_data, p, sizeof(int_data));
p += sizeof(int_data);

strcpy(p, str_data);
p += strlen(str_data) + 1;

send(sock, buf, p - buf, 0);

free(buf);

и чтение кода:

const int MAX_BUF_SIZE = 1024;
int int_data = 0;
const char *str_data = NULL;

char *buf = (char*) malloc(MAX_BUF_SIZE);
char *p = buf;

recv(sock, buf, MAX_BUF_SIZE, 0);

memcpy(p, &int_data, sizeof(int_data));
p += sizeof(int_data);

str_data = malloc(strlen(p) + 1);
strcpy(str_data, p);
p += strlen(p) + 1;

free(buf);

а сложные объекты необходимо сериализовать в поток байтов.

Примечание 1. Пример кода действителен, если и сервер, и клиент используют одни и те же платформы (x32 / x64 / ...), что означает, что int имеет одинаковое количество байтов и порядок байтов одинаков.

Примечание 2: Написание кода должно проверять отсутствие переполнения буфера (MAX_BUF_SIZE) на каждом шаге.

person dma_k    schedule 22.08.2011
comment
для целого числа следует использовать reinterpret_cast ‹char *› (i)? - person Pilpel; 22.08.2011
comment
(это легко) - для тех, кто умеет. Если вам придется задать этот вопрос, вы не найдете htons и htonl(). (@Pilpel: hton означает Host TO Network; он изменяет порядок байтов в соответствии с порядком байтов TCP / IP. При приеме вы должны использовать функцию ntoh. Оба существуют в 's' (короткое, 16 бит) и ' l '(длинная, 32 бита) версия. - person MSalters; 22.08.2011
comment
Как это отвечает на мой вопрос? функции ntoh не принимают указатели на символы и не делают их целыми числами - person Pilpel; 22.08.2011
comment
@ Пилпель: Не прямо. Это шаг, который вам нужно сделать до reinterpret_cast<char*>(&result_of_htonl) - person MSalters; 22.08.2011
comment
Понятно. Значит, слово host в hton может быть как клиентским, так и серверным кодом, верно? - person Pilpel; 22.08.2011
comment
@Pilpel: Я не понимаю, почему нам нужно менять байты местами, прежде чем помещать их в буфер, а затем выполнять обратную операцию. Я бы использовал memcpy для копирования байтов (при условии, что int = 4 байта на серверной и клиентской платформе, и обе платформы, например, x86). - person dma_k; 22.08.2011
comment
Я запутался. Не могли бы вы опубликовать несколько строк кода, чтобы прояснить ситуацию? - person Pilpel; 22.08.2011
comment
@Pilpel: Я добавил образец. Извините, не тестировал, но надеюсь, вы уловили идею. - person dma_k; 22.08.2011

Просто сохраните значение в переменной, а затем приведите переменную к char*. Функции send() и recv() работают с двоичными данными, несмотря на принятие char* параметров.

Отправка:

int int_data = 4;
send(sock, (char*) &int_data, sizeof(int), 0);

Чтение:

int int_data;
recv(sock, (char*) &int_data, sizeof(int), 0);
person Remy Lebeau    schedule 22.08.2011

Как правило, самый простой способ - вывести целое число или объект в строку и отправить эту строку. Текстовые представления более переносимы, а также их легче отлаживать.

std::stringstream может быть полезным классом как для создания строки, так и для ее анализа на другом конце.

person MSalters    schedule 22.08.2011
comment
Эта сериализация неэффективна. Если вам не нужна кроссплатформенная переносимость, вы можете использовать memcpy semantik. Возьмите адрес объекта и его размер и передайте адрес и размер функциям winsock. Здесь вам понадобится гипс. Когда ваши данные содержат указатели на другие объекты, вы не можете использовать стиль memcpy. В этом случае вам понадобится сериализация. - person harper; 22.08.2011
comment
Неэффективно? Вы даже признаете, что это кроссплатформенность, так что это, безусловно, должно работать. - person MSalters; 22.08.2011
comment
Предположим, у меня есть объект с двумя элементами данных, x и y, когда x = 10 и y = 20. Вы рекомендуете мне отправлять его в виде обычного текста, например: 10 | 20? - person Pilpel; 23.08.2011