C++ 之间的低延迟 IPC和爪哇

发布于 2024-11-10 14:23:00 字数 821 浏览 0 评论 0原文

对于以下情况,实现 C++/Java IPC 的最佳方法是什么?

(最近有人问了类似的问题,但我的要求更具体)

  1. <我有两个程序——一个用 C++ 编写,另一个用 Java 编写——需要相互通信。两者都在同一台机器上运行。

  2. 程序相互发送消息。消息通常很短(少于几百字节),但大小可能为 100KB 或更大。

  3. 消息不需要确认(即不是像 HTTP 那样的请求/响应模型)。例如,C++ 程序向 Java 程序发送一条消息,Java 程序稍后可能会通过向 C++ 程序发送一条消息来进行回复——反之亦然。

  4. 理想的解决方案应具有 a) 非常低的延迟,b) 无安全麻烦(用户不必授权打开端口等)以及 c) 与平台无关。

我的第一个想法是使用套接字——每个程序都充当另一个程序的服务器。套接字比其他形式的IPC有更多的开销,而且我不知道如果我让系统自动分配端口号,服务器将如何通知客户端端口号。我还考虑过命名管道,但不同平台不支持它们(至少不一致)。 JNI 看起来像是一个选项,但它可以跨进程边界吗?

有什么建议吗?

谢谢!

后续问题

  1. 如果我使用套接字,我是否需要打开两个套接字以允许如上所述的异步通信?

What is the best way to implement C++/Java IPC for the following situation?

(Someone recently asked a similar question, but my requirements are more specific)

  1. I have two programs -- one written in C++, the other in Java -- that need to communicate with each other. Both are running on the same machine.

  2. The programs send messages to each other. Messages are typically short (less than a few hundred bytes), but could potentially be 100KB or more in size.

  3. Messages do not need to be acknowledged (i.e., not a request/response model like HTTP). For example, the C++ program sends a message to the Java program, and the Java program may reply by sending a message to the C++ program at a later time -- and vice versa.

  4. An ideal solution would have a) very low latency, b) no security hassles (user does not have to authorize ports to be opened etc.) and c) will be platform-agnostic.

My first thought was using sockets -- each program would act as a server to the other. Sockets have more overhead than other forms of IPC, and I don't know how the server would inform the client of the port number if I let the system auto-assign port numbers. I've also considered named pipes, but they are not supported (at least not consistently) across different platforms. JNI looks like an option, but can it cross process boundaries?

Any suggestions?

Thanks!

FOLLOW-UP QUESTIONS

  1. If I go with sockets, would I need to open two sockets to allow for asynchronous communication as described above?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

吾家有女初长成 2024-11-17 14:23:00

我建议您使用TCP套接字

根据我的经验,与应用程序的其他任务工作负载(至少是我用来开发的应用程序)相比,TCP 套接字的实际开销非常非常低。我的意思是,有时即使套接字的延迟是其他 IPC 机制延迟的两倍,在整个工作流程中它们的影响也很小。它省去了在 Java 应用程序和 C++ 应用程序之间进行 IPC 的麻烦,这最终将要求您使用使用 JNI 的特定 Java 库,以及 JNI 和库本身的开销。

实际上,我在 Java 应用程序中测量到,垃圾收集器的影响远比“环回”TCP 套接字造成的延迟重要得多。

此外,TCP 套接字比传统 IPC 更具可扩展性(并且可移植!)。如果将来您必须在不同的计算机上运行客户端和服务器怎么办?在“TCP 套接字”场景中,您必须进行 5 分钟的修改,在“传统 IPC”场景中,您必须重写整个 IPC 内容。

但是,您的应用程序的一般工作流程是什么?

即使不需要确认,我也建议使用 TCP(而不是 UDP)来避免未排序的交付(这会导致麻烦)当需要重新排列您收到的内容时 - 您的某些消息有 100KB,这不适合 UDP 数据包)。

回答你的上一个问题,为了让服务器通知客户端有关端口的信息,你可以让服务器使用特定的“端口”命令行参数启动客户端,或者让服务器在 /tmp 下保存一个小文件(或者另一个临时目录),里面写着端口号。

I'd suggest you to use TCP sockets.

The actual overhead of TCP sockets, as of my experience, is very very low compared to the other tasks' workload of the applications, at least the ones I use to develop. I mean, sometimes even if sockets' latency is twice as the latency of other IPC mechanisms, in the overall workflow they have very little impact. And it saves you the hassle of making IPC between a Java application and a C++ one, that will eventually require you to use a specific Java library that uses JNI, with the overhead of JNI and the one of the library itself.

I've actually measured, in my Java applications, that Garbage Collector impact is far more important than the latency caused by "loopback" TCP sockets.

Moreover, TCP sockets are more scalable (and portable!) than traditional IPC. What if in the future you'll have to run the client and the server on different machines? In the 'TCP sockets' scenario, you'll have to do a 5-minute hack, in the 'traditional IPC' scenario, you'll have to rewrite the whole IPC stuff.

However, what is the general workflow of your application?

Even if the acknowledgement is not required, I'd suggest to use TCP (and not UDP) to avoid unsorted delivery (which leads to pain in the ass when it comes to rearrange the stuff you received - some of your messages are 100KB and this doesn't fit in a UDP packet).

In reply to your last question, for the server to inform the client about the port, you can just make the server launch the client with a specific 'port' command line parameter, or make the server save a small file under /tmp (or another temporary directory) with the port number written inside.

凉城 2024-11-17 14:23:00

我听说过 ZeroMQ 专门针对此类场景的一些好消息。在某些情况下,它甚至声称比 TCP 更快。简而言之,尝试一下肯定不会有什么坏处。

I've heard good things about ZeroMQ for specifically these sort of scenarios. It even boasts to be faster than TCP in some cases. In short, certainly won't hurt to try it out.

梦里寻她 2024-11-17 14:23:00

另一种方法是使用内存映射文件,并通过检查编译器设置(无论您是否为 posix)来保持其可移植性。 POSIX 操作系统有 mmap() ,在 Windows 中您可以使用 CreateFileMapping()

在 boost 库中是 C++ 的可移植实现,在 java 中您应该能够使用 FileChannel()

此页面很好地解释了如何将其用于 IPC http://en.wikipedia。 org/wiki/内存映射文件

An alternative is using memory mapped files and keeping it portable by checking compiler settings if you are posix or not. POSIX OS's have mmap() and in windows you would use CreateFileMapping()

In the boost library is a portable implementation for C++ and in java you should be able to use FileChannel().

This page does a good job of explaining how this can be used for IPC http://en.wikipedia.org/wiki/Memory-mapped_file

醉南桥 2024-11-17 14:23:00

当您说非常低的延迟时,您需要对其进行限定。您可以通过 Socket 循环以 20 微秒的 RTT 发送消息。如果这足够快,我就会这么做。

如果这还不够快,我会将 C++ 放入 Java 应用程序中并通过 JNI 调用它。这将为您提供大约 30 纳秒的 RTT。

使用内存映射数据的问题是如何获得正确的互锁。您可能会找到一种适用于一个系统的解决方案,但可能不适用于其他系统。

When you say very low latency, you need to qualify that. You can send messages over a Socket loop back with a RTT of 20 microsecond. If this is fast enough, I would do that.

If this is not fast enough I would just place the C++ inside the Java application and call it via JNI. This would give you about 30 nano-second RTT.

The problem with using memory mapped data is getting the interlocking right. You might find a solution which works on one system, but might not work on others.

我早已燃尽 2024-11-17 14:23:00

使用 JNI 将允许访问系统中的所有可能性,而不仅仅是 Java 中直接支持的那些;例如,如果您使用共享内存,则这是必要的。然而,JNI 本身相当昂贵。

延迟问题很棘手,因为我所知道的机制都没有给出任何保证。总而言之,最快的可能是某种形式的共享内存,当数据存在时使用信号唤醒其他进程。这需要在 Java 端使用 JNI,但如果做得正确,可能仍会提供最低的延迟 — 然而,正确执行(确保没有消息丢失)可能绝非微不足道。基于 Unix 的平台确实支持排队信号,并在单独的线程中将它们作为事件处理;我不知道Windows。

除此之外,命名管道通常非常有效。延迟可以与共享内存一样好,但需要更多时间来获取数据(因为必须通过系统复制数据)。并且应该可以直接从 Java 访问它,而不需要使用 JNI。在 Unix 下,还可以将套接字配置为同样快速地响应(事实上,这就是命名管道的本质);我不知道 Java 接口是否支持这些配置选项,但是,我也不知道它们在 Windows 下是否可用。

Using JNI would allow access to all of the possiblities in the system, not just those supported directly in Java; it would be necessary, for example, if you used shared memory. JNI is, itself, rather expensive, however.

The question of latency is tricky, because none of the mechanisms I know given any guarantees. All in all, the fastest would probably be some form of shared memory, using signals to wake up the other process when data is present. This would require using JNI on the Java side, but done correctly, would probably still give the lowest latency—doing it correctly (ensuring that no messages get lost) can be far from trivial, however. Unix based platforms do support queueing signals, and handling them as events in a separate thread; I don't know about Windows.

Other than that, a named pipe is generally pretty effective; the latency can be as good as shared memory, but it takes more time to get the data through (since it must be copied through the system). And it should be possible to access it directly from Java, without using JNI. Under Unix, it's also possible to configure sockets to respond just as quickly (in fact, this is what a named pipe is under the hood); I don't know if the Java interface supports these configuration options, however, and again, I don't know whether they're available under Windows.

蝶舞 2024-11-17 14:23:00

另一种选择是使用嵌入式数据库(因为您正在考虑多个 IPC,我假设这两个应用程序都在同一台机器上)。

我之前曾开发过一个应用程序,其中 C++ 应用程序从各种渠道获取数据并将其放入数据库(内存数据库;TimesTen)中。为了向用户显示该数据,Java 应用程序将从数据库中查询它。

对于你的使用,我不知道你是否愿意考虑Oracle的Timesten,但是你也可以使用Berkeley的嵌入式DB。

An alternative would be to use an embedded DB (since you're considering multiple IPCs, I assume both the applications are on the same machine).

I use to work on an application earlier where the c++ application fetches data from all sorts of channels and put it in the DB (an in-memory database; TimesTen). In order to display that data to the user, the Java application would query it from the DB.

For your use, I don't know if you'd be willing to consider Oracle's Timesten, but you could as well use Berkeley's embedded DB.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文