【问题标题】:C++ Client to a Java Server(TCP/IP)C++ 客户端到 Java 服务器(TCP/IP)
【发布时间】:2012-10-10 17:33:43
【问题描述】:

首先,我对使用 sockect 和 TCP/IP 数据包进行网络非常陌生,如果您能以非常清晰的方式解释,我将不胜感激。我的机器人程序第一次尝试在我们当前的机器人上使用 kinect,但我们遇到了问题。目前他们用 java 编码,而他们计划用 C++ 编码 kinect。是否可以使用 TCP/IP 数据包在两种语言之间发送信息?我们需要一个 C++ 客户端和一个 Java 服务器。如果有人有链接或示例,我将不胜感激,谢谢!

【问题讨论】:

  • 当然,TCP/IP 与语言无关。但如果 Java 和 C++ 部分都在同一台机器上运行,您可以考虑使用 Java Native Interface 在 C++ 中创建 Kinect 接口,并让 Java 通过 JNI 使用它。
  • 如果你正在联网,你不需要 JNI,因为你将通过 Sockets 进行通信。
  • java 的套接字示例是通用且简单的。你的 C++ 目标是什么?视窗? LINUX?

标签: java c++ sockets tcp ip


【解决方案1】:

Java 和 C/C++ 之间通信的真正问题是字节顺序问题。如果您要发送二进制数据,您必须清楚完整地设计通信结构,包括数字大小(以字节为单位)、位顺序(lsb/msb、交换字节或短的非交换字节、整数和longs)和结构打包(结构中字段之间的填充字节数)。

如果可以避免,我建议您不要使用二进制通信。有两个原因;

  1. 无需担心位顺序、字节交换和结构打包。
  2. 窃听通信而不解码数据。您仍然有 ascii/unicode 问题。

编辑 在 C/C++ 中,数据的存储方式使 CPU 访问变得快速而轻松。类/结构的字段在字边界上对齐(因为大多数 CPU 只能以完整的字块访问内存),并且位被排序以匹配 CPU。但是,CPU 可以有不同的位顺序和字长(16、32、64,...)。大多数英特尔 CPU 都是小端,而大多数其他设计都是大端。为了让生活更有趣,java 虚拟机在每个平台上都是大端的。 http://en.wikipedia.org/wiki/Endianness

因此,如果您希望两台 C/C++ 机器能够通信,那么您必须以双方都能读取的方式发送数据。通常,要在异构环境中进行通信(称为“有线”),您需要指定所有通信都以特定格式完成。 TCP/IP 使用 MSB(最高有效位)排序。然后所有程序都必须从有线格式转换(如果需要)。

因为 CPU 以字长块的形式消耗内存,所以编译器会将填充字节放在不填充整个机器字的字段之间。对于读取 32 位字的机器,结构如下:

struct example1 {
  char someFlag;
  int  someCount;
};

实际上会占用 8 个字节的内存。第一个字段由一个数据字节和 3 个填充字节组成,因此整数引用在字边界上对齐。如果一个天真的通信器试图以这种结构发送数据,比如send(&example1, sizeof(example1)); 到另一个具有不同字长或字节顺序的系统,而另一个系统发送read(&example1, sizeof(example1));,那么 example1.someCount 的值可能与预计。

在您将 Java 投入其中之前,大部分内容通常都是学术性的。因为Java总是MSB格式。因此,从 C/C++ 应用程序发送到 Java 应用程序,即使在相同的硬件上,也可能导致同样的意外结果。

Java 包含我最喜欢的 I/O 类 java.nio.ByteBuffer。它能够从几乎任何来源读取整数、长整数、浮点数和双精度数。如果您知道数据是如何创建的,它将读取它。 ByteBuffer有getShortgetInt等方法可以获取任意类型,还有order()方法可以设置数据的字节顺序。

【讨论】:

  • 我真的很感谢大家的帮助,只是为了进一步扩展您的答案@Zagrev:如果我将数据从 kinect 发送到机器人(java),我不需要使用二进制数据发送它?如果没有,我将如何发送信息?
【解决方案2】:

当您希望两个程序通过网络相互通信时,您需要定义一个protocol

在 TCP 之上定义的协议需要指定一种方法来告诉接收者何时接收到整个消息。两种常见的方法是:

  • 指定一些特殊的数据序列来表示“结束”。一个例子是 HTTP,它使用一个特殊的 CRLF 字符来表示消息的非有效负载部分的结束。
  • 在消息的某些预定义部分中指定消息的长度。一个示例是 HTTP,它在“Content-Length”标头中指定有效负载的长度。

您可以在此处找到有关 HTTP 消息结构的更多信息:http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html

此外,您可能希望使用与平台无关的格式来编码有效负载。一个很好的二进制格式是 Google 的 Protocol Buffer,它在 Java 和 C++ 中得到很好的支持:http://code.google.com/p/protobuf/

【讨论】:

    【解决方案3】:

    当然,您可以在实现不同语言的程序之间交换信息。 (您是否期望整个 Internet 都使用 Java?)

    这是我在谷歌搜索“socket programming {Java, C++}”后发现的:

    http://codebase.eu/tutorial/linux-socket-programming-c/ - 好像没问题

    http://www.javaworld.com/jw-12-1996/jw-12-sockets.html - Java 教程

    但要小心。根据您的硬件架构,您在交换二进制数据(字节顺序等)时可能会遇到一些问题。当您使用面向对象的语言时,您可以考虑使用某种处理低级通信的中间件 - 例如Ice。但是,在您的情况下,这可能有点矫枉过正。

    【讨论】:

      猜你喜欢
      • 2019-02-26
      • 1970-01-01
      • 2019-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多