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

Я работаю над небольшим клиентским приложением на чистом 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);
}

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


Ответы (1)


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

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

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

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

person David Schwartz    schedule 03.09.2015
comment
почему вы читаете только один байт в первом вызове Хммм, возможно, может быть несколько сообщений, и, читая как можно больше байтов, код может не получить несколько или частичные сообщения, а затем управлять этим? - person chux - Reinstate Monica; 04.09.2015
comment
@chux Да, конечно. Такова природа TCP. Прямо сейчас он заставляет ядро ​​делать это. Он уже обрабатывает частичные сообщения. - person David Schwartz; 04.09.2015
comment
Спасибо за очень быстрый ответ! Я забыл удалить это заявление о сне, я просто хочу кое-что проверить. Простите за это. Я читаю только один байт, а затем остальную часть пакета, потому что не хочу анализировать большой буфер [512] или [1024], где может быть много пакетов или какие-то неполные. Мне лень это кодировать. - person ; 04.09.2015
comment
@Cpt.Rambler Без сна вы просто сожжете процессор в тесном цикле в ожидании данных. - person David Schwartz; 04.09.2015
comment
@DavidSchwartz Я знаю, ты прав. Тогда что вы понимаете под фальшивой промежуточной вещью, этим циклом do-while? - person ; 04.09.2015
comment
@Cpt.Rambler Да. Точно. Если вы просто хотите заблокировать, пока что-то не произойдет, используйте блокирующие сокеты. Если вы используете неблокирующие сокеты, используйте их с какой-нибудь разумной схемой обнаружения сокетов, такой как опрос. (Почему вы все равно используете неблокирующие сокеты, если вам просто нужно подделать способ блокировки на них?) - person David Schwartz; 04.09.2015