2015-08-26 4 views
3

У меня есть программа, которая выделяет 32-битный Int, а затем пытается читать 4 байта из сокета в междунар с использованием чтения (2)C: неполное прочитать в Int

Иногда чтение является неполным и возвращается прочитав скажем, 2 байта. Есть ли способ оправиться от этого? Я полагаю, что я должен создать указатель на полпути в int, чтобы иметь возможность выполнить другое чтение.

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

+5

Обработка сериализации в C * является * уродливым .. –

+0

Возможно, я неправильно понял, но вы могли сначала прочитать все четыре байта и только потом десериализовать их? Обратите внимание, что вы, вероятно, должны делать это в любом случае, если вам небезразлично. – Patrick87

+2

@EugeneSh. * Обработка сериализации уродлива. * FTFY – Patrick87

ответ

0

Отказ от ответственности: это плохой код. Не делай этого.

int value = 0; 
int bytes = 0; 
while ((bytes += read(((char*)&value)+bytes, 4-bytes)) < 4); 
+4

Согласен. Не публикуйте его. – EJP

+0

@EJP Просто дайте ему то, что он хочет, основываясь на комментариях. Не беспокойтесь о том, что он настаивает на том, чтобы делать с веревкой. – Patrick87

3

Сначала вам необходимо убедиться, что прочитали 4 байта. Вы делаете это с помощью функции, аналогичной this один (несколько измененных):

#include <sys/types.h> 
#include <sys/socket.h> 

int readall(int s, char *buf, int *len) 
{ 
    int total = 0;  // how many bytes we've read 
    int bytesleft = *len; // how many we have left to read 
    int n = -1; 

    while(total < *len) { 
     n = read(s, buf+total, bytesleft, 0); 
     if (n <= 0) { break; } 
     total += n; 
     bytesleft -= n; 
    } 

    *len = total; // return number actually read here 

    return (n<=0)?-1:0; // return -1 on failure, 0 on success 
} 

И после этого вы можете собрать целое число, используя эти четыре байта.

+1

Вам также нужно разбить 'n == 0', иначе вы будете навечно зацикливаться на конце потока. – EJP

+0

@EJP: Вы имеете в виду, если другая сторона отключается? Хорошо, я исправлю код (и предположим неудачу, если это так, вернув -1, OP может изменить его для своих нужд). –

+0

@EJP: И не может быть никаких действительных случаев, когда возврат равен 0 и говорит на следующем recv, может быть, он что-то читает? –

0

Так с информацией здесь и в What's the correct way to add 1 byte to a pointer in C/C++? я пришел к выводу, что:

  1. адресации в междунар может вызвать проблемы с выравниванием на некоторых архитектурах.
  2. Вы можете попытаться обойти это с помощью типа каламбуров (союз между int и char[]), но на практике этот метод кажется не более надежным, чем 1.
  3. не
  4. Единственный по-настоящему портативный способ сделать указатель байт арифметика используя char * в char[]. Следовательно, правильный способ обработки этой ситуации - прочитать все байты в массиве и впоследствии построить int.
  5. Реконструкция в int может быть выполнена ntohl или бит-сдвигом. Bitshifting переносится между конечной машиной хоста с it is defined in terms of multiplication.

Итак, где это нас покидает? Ну, переносная опция должна читать в char[] и восстанавливать с битрейтом или ntohl. Непереносимый способ состоит в том, чтобы указать char * в ваш int, как предложил @ Patrick87.

Я пошел по прагматичной дороге и только что создал char* в мой int. Хорошо работал на моей целевой платформе.