#c #winsock
#c #winsock
Вопрос:
Я знаю, что загрузка функции send()
через winsocket является указателем на массив char, я хочу использовать его для отправки набора фиксированных значений, я бы хотел написать что-то вроде этого
send(socket, FIXED_VALUE_N, (int)strnlen(FIXED_VALUE), 0);
В то же время было бы удобно для удобочитаемости и удобства настройки пар (имя, значение) таким или аналогичным образом (считайте это псевдокодом):
FIXED_VALUE_1 <- 1
FIXED_VALUE_2 <- 2
FIXED_VALUE_3 <- 3
...
Для чего я могу использовать? Я отбросил перечисления, поскольку они являются целыми числами, и я считаю пустой тратой времени на четыре отправки по одному байту каждая. Альтернативой было бы определить макрос, но я не могу определить макрос для байта, а не только для строки, поскольку я хочу отправить ’27’, а не ‘2’,’7′.
Заранее спасибо.
Комментарии:
1. Я думаю, что этот стек более подходит: codereview.stackexchange.com
2. Рассматривали ли вы возможность объединения строк ваших данных в группы, разделенные запятыми? Это позволило бы отправлять несколько пар и анализировать их на принимающей стороне.
3. Хм.
strnlen
требуется два аргумента, просто предупреждаю.4. Вы также можете написать макрос, чтобы превратить ваш номер в кавычки.
5. Что-то вроде
#define FIXED_VALUE_N "123"
? Разве это не строка из 3 байт?
Ответ №1:
Во-первых, обратите внимание, что, как написано,
send(socket, FIXED_VALUE_N, (int)strnlen(FIXED_VALUE_N), 0);
^^ //added to correct typo
FIXED_VALUE_N должно быть в форме const char *, чтобы быть правильным. И, strnlen()
требуется два аргумента, (второй — size_t number_of_elements
).
РЕДАКТИРОВАТЬ 3 (обращаясь к последнему вопросу комментария)
Если вы объявите и заполните FIXED_VALUE_N как:
const char FIXED_VALUE_N[2];
FIXED_VALUE_N[0]=0x1B;
А также исправить синтаксис третьего аргумента…
send(socket, FIXED_VALUE_N, 1, 0); //hard-coded third argument for illustration
… Это сработает, потому что теперь вы передаете указатель на const char ( const char *
) во втором аргументе и соответствуете синтаксическим требованиям send()
прототипа.
(окончательная ПРАВКА 3)
Имея это в виду, рассматривали ли вы объединение строк данных в группы, разделенные запятыми? Это позволило бы отправлять несколько значений и анализировать их на принимающей стороне. Что-то вроде:
#define MAX_SIZE 100 //pick a value that makes sense for your application, I randomly picked 100
char buffer[MAX_SIZE];
int len=0;
sprintf(buffer, "%d,%d,%d", FIXED_VALUE_1, FIXED_VALUE_2,FIXED_VALUE_3);
len = strlen(buffer); //****
send(socket, buffer, len 1, 0); // strlen() does not include `` byte in its return
// value. Use `len 1` to make room for
// terminator - added by the sprintf() function.
Отправил бы "1,2,3"
Что касается вашего заявления: поскольку я хочу отправить ’27’, а не ‘2’, ‘7’.
Не используйте запятые в инструкции форматирования sprintf()
, и отправленные вами числа будут последовательными.
sprintf(buffer, "%d%d%d", FIXED_VALUE_1, FIXED_VALUE_2,FIXED_VALUE_3);
^^^^^^
Отправил бы "123"
РЕДАКТИРОВАТЬ (заполнить len, используя возврат sprintf)
Также, как указал @Jack:
Вместо использования strlen()
вы можете сохранить строку кода, просто установив len = sprintf(…); в строке выше. (см. ****
Фрагмент кода выше) as sprintf()
возвращает количество переданных символов или отрицательное значение, если произошла ошибка вывода. (если результат отрицательный, произошла ошибка)
ОТРЕДАКТИРУЙТЕ 2 (байтовые данные, согласно вашему комментарию выше)
Если вы хотите отправлять данные в наименьшем (наиболее эффективном) форм-факторе, используйте байтовые данные. байтовые данные могут храниться в массиве символов:
char *byte_data=0;
byte_data = malloc(NUM_BYTES_RQD);//#define NUM_BYTES_RQD as needed,
//or pass in size info as an argument
//from calling function
//populate byte_data
for(i=0;<NUM_BYTES_RQD;i )
{
byte_data[i]=<enter byte value here>
}
send(socket, byte_data, len, 0);
free(byte_data);
Комментарии:
1.
sprintf()
верните количество байтов, записанных в буфер, чтобы вы могли использовать его вместоstrlen(buffer)
2. Моя точка зрения заключалась не только в сохранении строки кода, но и в производительности. Если вы можете избежать вычисления одного и того же значения дважды (или в режиме), вам не следует этого делать.
3. @Джек — согласен. Увеличение производительности предполагалось за счет сохранения строки кода 🙂
4. Не отправляя
''
, как получающая сторона узнает, когда заканчивается содержимое одногоsend()
и начинается другое? Подумайтеsend(socket, buffer, len 1, 0);
или допишите запятую.5. @chux — Спасибо. Добавил это и прокомментировал. Но важно отметить: методы recv() сильно различаются в зависимости от реализации протоколов, использующих их. Я использовал протоколы, в которых определенная серия байтов указывала на конец блока данных. Поэтому я не думаю, что всегда необходимо включать для завершения байтовых данных.
Ответ №2:
Рассматривали ли вы возможность использования макроса X?
#define X(a, b) a,
#define FIXED_VALUES_TABLE
X(FIXED_VALUE_1, "1")
X(FIXED_VALUE_2, "2")
// ...
enum { FIXED_VALUES_TABLE };
#undef x
#define X(a, b) b,
const char *fixed_values_values[] = { FIXED_VALUES_TABLE };
#undef x
И тогда вы можете использовать вот так:
char *val = fixed_values_values[FIXED_VALUE_1];
char *va2 = fixed_values_values[FIXED_VALUE_2];
если вы хотите объединить их, вы можете использовать malloc() strcat()
.
Комментарии:
1. Я не слышал об этом. Очень приятно.