Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Использование беззнакового символа вместо символа из-за его диапазона

Автор вопроса: CommunityОтветов: 1

Я работаю над небольшим клиентским приложением на чистом C (мое первое:/), которое использует сокет TCP для связи с сервером. Сервер отправляет мне пакет (структура C), в котором первый байт содержит размер пакета.

Проблема в том, что сервер использует беззнаковый символ для представления размера пакета, потому что символ имеет знак (от -128 до +127), а +127 недостаточно для представления размера, который может достигать 255 в некоторых пакетах. => Мне нужен беззнаковый буфер символов;

В Linux вторым параметром функции recv() является void *, что означает, что я могу объявить буфер void *, и проблем не будет. Но recv() в Windows (MinGW) имеет char * вместо void *. Что дает мне предупреждение "Несоответствие типа параметра: несовместимые типы указателей" char * "и" unsigned char * ""

Можно ли решить эту проблему? Вот код. Спасибо.

PS: я использую НЕБЛОКИРУЕМЫЕ сокеты.

 int recvsize = 0;
unsigned char tmpsize;
int index = 0;
unsigned char *buffer;

while (1) {

    recvsize = recv(server, &tmpsize, sizeof(unsigned char), 0); // every packet starts with one byte where is its length

    if (recvsize > 0 ) {
         buffer = malloc(tmpsize * sizeof(unsigned char)); //memory allocation according to the size of packet
         buffer[0] = tmpsize--; //get back the size value to the buffer
         recvsize = 0;


        do { //loop over and over until you do not have all bytes of the packet
            recvsize = recv(server, &buffer[++index], tmpsize, 0);

            if (recvsize == 0)
                break;


            tmpsize -=recvsize;
            index += recvsize;

        } while (tmpsize != 0);

    }
sleep(50);
}
  • char может быть подписано на вашей платформе. Стандарт оставляет это на усмотрение реализации. В общем, при передаче данных между разными системами (и в большинстве случаев также в одной системе) предпочтительным способом является использование типов stdint.h и надлежащая сериализация. В противном случае ждет брезент. too honest for this site 04.09.2015
  • Примечание. sizeof(unsigned char) всегда равно 1, поэтому ... * sizeof(unsigned char) не требуется. Если код хочет отметить масштабирование по размеру переменной, предложите buffer = malloc(tmpsize * sizeof *buffer) chux - Reinstate Monica 04.09.2015

ctcpsocketscharunsigned

Ответы

Ответ 1 · рейтинг 2 · David Schwartz

Просто укажите указатель на правильный тип. Так что используйте:

(char *) (&buffer[++index])

Кроме того, почему вы создаете схему блокировки, повторяя неблокирующую операцию в спящем цикле? Либо используйте блокирующие сокеты, либо используйте неблокирующие сокеты, но не создавайте какие-то поддельные промежуточные вещи. (Если, например, вредоносный или медленный клиент отправляет вам только один байт, вы будете вращаться на recv.)

Наконец, почему вы читаете только один байт при первом вызове recv? Вам в любом случае нужны остальные данные, так зачем заставлять ядро ​​выдавать их вам крошечными каплями? Почему бы не прочитать как можно больше байтов и, если повезет, избежать необходимости вызывать recv во второй раз?

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы