Как я могу отправить массив целых чисел через TCP в C? - PullRequest
2 голосов
/ 23 марта 2009

Я склонен полагать, что write() может отправлять только буферы данных байта (т.е. знаковый символ), так как я могу отправить массив длинных целых чисел, используя функцию C write() в sys / socket.h библиотека

Очевидно, я не могу просто привести или преобразовать long в char, так как любые числа свыше 127 будут искажены.

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

Контрольный вопрос:

Почему я получаю странные результаты при чтении массива целых чисел из сокета TCP?

Ответы [ 7 ]

15 голосов
/ 23 марта 2009

прототип для записи:

ssize_t write(int fd, const void *buf, size_t count);

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

EDIT:

Однако я рекомендую вам также отправить количество целых чисел, которое вы планируете отправить первым, чтобы получатель знал, сколько читать. Примерно так (проверка ошибок для краткости опущена):

int x[10] = { ... };
int count = 10;
write(sock, &count, sizeof(count));
write(sock, x, sizeof(x));

ПРИМЕЧАНИЕ: если массив из динамической памяти (как вы malloc его редактировали), вы не можете использовать sizeof для него. В этом случае количество будет равно: sizeof(int) * element_count

EDIT:

Как заметил Брайан Митчелл , вам, вероятно, также следует остерегаться вопросов endian . Это имеет место при отправке любого многобайтового значения (как в подсчете, который я рекомендовал, а также для каждого элемента массива). Это делается с помощью функций: htons / htonl и ntohs / ntohl.

6 голосов
/ 23 марта 2009

Писать может делать то, что вы хотите, но есть некоторые вещи, о которых нужно знать:

1: Вы можете получить частичную запись, которая не находится на границе int, поэтому вы должны быть готовы справиться с этой ситуацией

2: если код должен быть переносимым, вы должны преобразовать свой массив в определенный порядок байтов или закодировать порядок байтов в сообщении.

2 голосов
/ 23 марта 2009

Простейший способ отправки единственного целого числа (при условии 4-байтовых целых):

int tmp = htonl(myInt);
write(socket, &tmp, 4);

где htonl - это функция, которая преобразует int в сетевой порядок байтов . (Точно так же. Когда вы читаете из сокета, функция ntohl может использоваться для преобразования обратно в порядок байтов хоста.)

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

2 голосов
/ 23 марта 2009

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

Просто убедитесь, что вы указали write() с правильным размером в байтах вашего массива - это будет количество элементов, умноженное на sizeof (long) в вашем случае.

1 голос
/ 20 апреля 2011

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

Например:

char tcp[100];

tcp[0] = 0;
tcp[1] = 0xA;
tcp[2] = 0xB;
tcp[3] = 0xC;
.
.

// Send the character array
write(sock, tcp, sizeof(tcp));
1 голос
/ 23 марта 2009

Было бы лучше иметь функции сериализации / десериализации в вашей клиент-серверной программе.

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

При получении данных десериализовать данные из буфера в вашу собственную интерпретацию.

Вы можете интерпретировать байтовый буфер в любой форме, как вам нравится. Может содержать базовый тип данных, объекты и т. Д.

Просто позаботьтесь о порядке байтов и выравнивании.

0 голосов
/ 23 марта 2009

Я думаю, что вам нужно придумать здесь протокол .

Предположим, ваш массив целых чисел:

100, 99, 98, 97

Вместо записи целых чисел непосредственно в буфер, я бы «сериализовал» массив, превратив его в строковое представление. Строка может быть:

"100,99,98,97"

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

Это более стандартизировано, доступно для чтения и означает, что людям не нужно думать о порядке байтов hi / lo и других глупых вещах.

// Сарказм

Если бы вы работали в .NET или Java, вы, вероятно, закодировали бы его в XML, например так:

<ArrayOfInt><Int>100</Int><Int>99</Int><Int>98</Int><Int>97</Int></ArrayOfInt>

:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...