Преобразование буфера Char в массив шорт - PullRequest
1 голос
/ 07 октября 2011

У меня есть буфер char *, который заполняется функцией API. Мне нужно взять данные, содержащиеся в этом указателе, преобразовать их в беззнаковые шорты и перевести их в сетевой формат (htons ()) для отправки по UDP. Вот мой код (не все, хотя по нескольким причинам)

Код ниже будет работать, но данные на другой стороне плохие (не шорты или не переведенные по сети)

    char * pcZap;
    while(1)
    {
        unsigned short *ps;
        unsigned short short_buffer[4096];

        write_reg(to start xfer);
        return_val = get_packet(fd, &pcZap, &uLen, &uLob);
        check_size_of_uLen_and_uLob(); //make sure we got a packet

        // here I need to chage pcZap to (unsigned short *) and translate to network            

        sendto(sockFd,pcZap,size,0,(struct sockaddr *)Server_addr,
               sizeof(struct sockaddr));
        return_val = free_packet(fd, pcZap);
        thread_check_for_exit();
    }

Любая помощь будет оценена. Спасибо.

Ответы [ 3 ]

0 голосов
/ 07 октября 2011

Предполагая, что в вашем буфере имеется 4080 байтов, состоящих из 16-битных выборок, это будет означать, что у вас будет 2040 16-битных выборок в 4080 байтах вашего буфера (16 байтов зарезервированы для заголовка). Поэтому вы можете сделать следующее:

#define MAXBUFSIZE 4096
#define MAXSHORTSIZE 2040

unsigned char pcZap[MAXBUFSIZE];
unsigned ushort[MAXSHORTSIZE];

//get the value of the returned packed length in uLen, and the header in uLob

unsigned short* ptr = (unsigned short*)(pcZap + uLob);
for (int i=0; i < ((uLen - uLob) / 2); i++)
{
    ushort[i] = htons(*ptr++);
}

Теперь ваш массив ushort будет состоять из значений сетевого порядка unsigned short, преобразованных из исходных значений в массиве pcZap. Затем при вызове sendto() обязательно используйте значения из ushort, а не значения из pcZap.

0 голосов
/ 07 октября 2011

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

size_t i;
size_t len = uLen - 16 - uLob;
size_t offset = uLob + 16;

if(len % 2 != 0) {
  ..error not a multiple of 16 bit shorts...
}
//now, if you're on a little endian host (assuming the shorts in 
//pcZap is laid out as the host endian...), just swap around the bytes
//to convert the shorts to network endian.
for(i = 0; i < len; i+=2) {
    //swap(&pcZap[offset + i],&pcZap[offset + i + 1]);
    char tmp = pcZap[offset + i];
    pcZap[offset + i] =  pcZap[offset + i + 1]; 
    pcZap[offset + i + 1] = tmp;
}
//if you're on a big endian host, forget the above loop, the data
//is already in big/network endian layout.

//and just send the data.
if(sendto(sockFd,pcZap + offset,len,0,(struct sockaddr *)&Server_addr,
               sizeof Server_addr) == -1) {
   perror("sendto");
}

Обратите внимание, что ваш код содержал sizeof(struct sockaddr) в вызове sendto (), что неверно, вы хотите, чтобы это был фактический размер Server_addr.

0 голосов
/ 07 октября 2011

Если ваш массив символов завершается нулем, то вы можете просто сделать:

for (int i=0; i<strlen(CHAR_ARRAY); i++)
     short_buffer[i] = (unsigned short) CHAR_ARRAY[i];

Если массив не завершен на нуль, вам нужно выяснить, как долго он точно, а затем заменить strlen(CHAR_ARRAY) на это значение.

...