2015-01-05 2 views
0

Я пытаюсь отправить знаковые целые числа Java по TCP на клиент C.Отправка Java int на C через TCP

На стороне Java я пишу целые числа к OutputStream так:

static ByteBuffer wrapped = ByteBuffer.allocateDirect(4); // big-endian by default 

public static void putInt(OutputStream out, int nr) throws IOException { 
    wrapped.rewind(); 
    wrapped.putInt(nr); 
    wrapped.rewind(); 

    for (int i = 0; i < 4; i++) 
     out.write(wrapped.get()); 
} 

На стороне С, я прочитал целые числа, как так:

int cnt = 0; 
char buf[1]; 
char sizebuf[4]; 
while(cnt < 4) { 
     iResult = recv(ConnectSocket, buf, 1, 0); 
     if (iResult <= 0) continue; 

     sizebuf[cnt] = buf[0]; 
     cnt++; 
} 

Однако, как я преобразовать массив символов в целое число в C?

Редактировать

Я попробовал следующее (и наоборот):

int charsToInt(char* array) { 
    return (array[3] << 24) | (array[2] << 16) | (array[1] << 8) | array[0]; 
} 

Отредактировано снова, потому что я забыл теги.

данных

Для примера того, что происходит в данный момент:

я получаю:

char 0 
char 0 
char 12 
char -64 
the int becomes 2448 

и использовать эту функцию для создания Int из массива полукокса:

int charsToInt(char* array) { 
    return ntohl(*((int*) array)); 
} 

Я ожидаю, что подписанный i nteger: 3264

Update Я расследую больше после некоторого сна ..

Update У меня есть клиент Java, который интерпретирует целые числа правильно и получает те же байты:

0 
0 
12 
-64 
+0

@AndyThomas: Да, но он зацикливается –

+0

Вы говорите: «Я пробовал следующее», но вы не говорите, как вы знаете, что это не сработало. Каковы были значения в массиве, которые вы предоставили, и каково было целое число, которое было возвращено? Вы подтвердили это в отладчике или распечатали значение? Если вы напечатали его, какое заявление вы использовали для его печати? Эта информация важна. Вот пример его работы: http://ideone.com/EZNCGs – indiv

+0

@RobotRock: можете ли вы, по крайней мере, печатать отдельные байты –

ответ

1

Это зависит от цели, но вы хотите:

int x = sizebuf[0] + 
     (sizebuf[1] << 8) + 
     (sizebuf[2] << 16) + 
     (sizebuf[3] << 24); 

или:

int x = sizebuf[3] + 
     (sizebuf[2] << 8) + 
     (sizebuf[1] << 16) + 
     (sizebuf[0] << 24); 

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

int x = (sizebuf[3] & 0x000000ff) + 
     ((sizebuf[2] << 8) & 0x0000ff00) + 
     ((sizebuf[1] << 16) & 0x00ff0000) + 
     ((sizebuf[0] << 24) & 0xff000000); 
+0

Я пробовал выше, безрезультатно. – RobotRock

+0

@RobotRock: Можете ли вы печатать отдельные байты? Что вы получаете на стороне C? –

+1

@ user300234, никакие приведения не требуются. Целочисленные акции по умолчанию позаботятся об этом. –

0

Чтобы преобразовать вас массив символов, одна возможность заключается в том, чтобы привести его в целое * и сохранить результат:

int result = *((int*) sizebuf) 

Это действительная и одна строка. Другая возможность - вычислить целое число из символов.

for (i = 0 ; i < 4; i++) 
    result = result << sizeof(char) + buf[0] 

Выберите тот, который вы предпочитаете.

Alexis.

Редактировать: sizeof (char) равен 1, потому что sizeof возвращает результат байта. Таким образом, правая линия: результата = результат < < (SizeOf (Char) * 8) + ЬиЙ [0]

+1

'sizeof (char)' is '1'. Следите за тем, чтобы проблемы выравнивания были также с вашим первым примером. –

+0

Потому что я этого не знал, но, похоже, это хорошая идея. Тем не менее, я не уверен, что это так «классика», как в странных заголовках. Что происходит с переносимостью? – AlexisBRENON

+0

@CarlNorum Спасибо, чтобы указать размер ошибки. Я вполне понимаю проблему выравнивания, но я никогда не сталкивался с этой ошибкой с момента, когда я код. – AlexisBRENON

1

Классическая библиотека C имеет метод, который вы хотите уже, и это не зависит от машины байт: ntohl !

// buf is a char */uint8_t * 
uint32_t from_network = *((uint32_t *) buf); 
uint32_t ret = ntohl(from_network); 

Это и htonl для обратного и т.д. ожидать, что «сетевой порядок» большой порядок байт.

(код выше, предполагает, что buf имеет, по меньшей мере, 4 байта, тип возвращаемого значения и тип аргументов, из ntohl и htonl являются uint32_t, а JLS определяет int как 4 байта, так что вы гарантированно результат)

+1

Остерегайтесь проблем с выравниванием. –

+0

@CarlNorum hmwell, этот код предполагает, что 'buf' является' char * ', да; это достаточно хорошо, не так ли? – fge

+1

Нет, этого недостаточно. Если 'buf' не выровнен по 32 битам, например, этот код будет аварийно завершен на ARM7. –

Смежные вопросы