【问题标题】:Sending Java int to C over TCP通过 TCP 将 Java int 发送到 C
【发布时间】:2015-03-03 11:19:26
【问题描述】:

我正在尝试通过 TCP 将 Java 的有符号整数发送到 C 客户端。

在 Java 端,我将整数写入输出流,如下所示:

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());
}

在 C 端,我像这样读取整数:

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 中将 char 数组转换为整数?

编辑

我尝试了以下方法(反之亦然):

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

并使用从 char 数组创建 int 的函数:

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

我希望有符号整数:3264

更新 睡一觉后我会调查更多..

更新 我有一个 Java 客户端,它可以正确解释整数并接收完全相同的字节:

0
0
12
-64

【问题讨论】:

  • @AndyThomas:是的,但他正在循环播放
  • 你说“我已经尝试了以下”,但你没有说你怎么知道它不起作用。您提供的数组中的值是什么,返回的整数是什么?您是否在调试器中验证了这一点或打印了该值?如果你打印它,你用来打印它的语句是什么?这些信息很重要。这是一个工作示例:ideone.com/EZNCGs
  • @RobotRock:你至少可以打印单个字节吗
  • 我正在努力包含松散的字符和预期的输出,我会尽快将它们包括在内。
  • 您遇到了符号扩展问题。请参阅我的更新答案。

标签: java c tcp


【解决方案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);

【讨论】:

  • @RobotRock:你能打印单个字节吗?你在 C 方面得到了什么?
  • @user300234,不需要强制转换。默认的整数提升会处理它。
  • 您更新后的答案与 fge 的答案相同; 2448.跨度>
  • 那你输入的数据是错误的。你检查了吗?
  • @Carl Norum:我刚刚检查过,可能 2448 实际上是正确的。 2448 是我对下一个整数的预期,这可能不是巧合。
【解决方案2】:

经典的 C 库已经有了你想要的方法,并且独立于机器字节序:ntohl!

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

这和htonl 的反向等期望“网络顺序”是大端。

(上面的代码假设buf至少有4个字节;ntohlhtonl的返回类型和参数类型是uint32_t;JLS将int定义为4个字节,所以保证结果)

【讨论】:

  • 注意对齐问题。
  • @CarlNorum hmwell,这段代码假设bufchar *,是的;这已经足够了,对吧?
  • 不,这还不够。例如,如果 buf 不是 32 位对齐的,则此代码会在 ARM7 上崩溃。
【解决方案3】:

要转换您的 char 数组,一种可能性是将其转换为 int* 并存储结果:

int result = *((int*) sizebuf)

这是有效的,只有一行。其他可能性是从字符计算整数。

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

选择你喜欢的那个。

亚历克西斯。

编辑: sizeof(char) 为 1,因为 sizeof 返回一个 Byte 结果。所以正确的行是: 结果 = 结果

【讨论】:

  • sizeof(char)1。还要注意第一个示例的对齐问题。
  • 因为我不知道,但这似乎是个好主意。尽管如此,我不确定它是否像在奇怪的标题中那样“经典”。便携性会怎样?
  • @CarlNorum 感谢指出 sizeof 错误。我很清楚对齐问题,但我在编写代码时从未遇到过此错误。
猜你喜欢
  • 2013-07-21
  • 2010-12-16
  • 2011-04-30
  • 2014-10-05
  • 2019-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多