有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

C++与java之间的低延时IPC

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

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

    我有两个程序,一个用C++编写,另一个用java编写,需要互相交流。两者都在同一台机器上运行

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

  2. 消息不需要被确认(即,不是像HTTP这样的请求/响应模型)。例如,C++程序向java程序发送消息,java程序可以在稍后的时间向C++程序发送消息,反之亦然。p>

  3. 理想的解决方案应该是a)非常低的延迟,b)没有安全问题(用户不必授权打开端口等),c)与平台无关

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

有什么建议吗

谢谢

后续问题

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

共 (6) 个答案

  1. # 1 楼答案

    当你说非常低的延迟时,你需要限定它。您可以使用20微秒的RTT通过套接字环回发送消息。如果这足够快,我会这么做

    如果这不够快,我只会把C++放在java应用程序中,然后通过JNI调用它。这将给你30纳秒的RTT

    使用内存映射数据的问题在于正确地获取联锁。您可能会找到一个在一个系统上有效,但在其他系统上可能不起作用的解决方案

  2. # 2 楼答案

    我建议您使用TCP套接字

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

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

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

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

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

    在回答上一个问题时,为了让服务器通知客户端端口,您可以让服务器使用特定的“port”命令行参数启动客户端,或者让服务器在/tmp(或另一个临时目录)下保存一个小文件,并在其中写入端口号

  3. # 3 楼答案

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

    在Boost库中是一个可移植的C++实现,在java中,你应该能够使用^ {CD3>}。p>

    本页很好地解释了如何将其用于IPChttp://en.wikipedia.org/wiki/Memory-mapped_file

  4. # 4 楼答案

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

    <>我以前使用过一个应用程序,在那里C++应用程序从各种通道中获取数据并将其放入数据库中(AN内存数据库;TimeStand)。为了向用户显示该数据,Java应用程序将从数据库中查询该数据

    对于您的使用,我不知道您是否愿意考虑Oracle的TimeStin,但您也可以使用伯克利的嵌入式DB。p>
  5. # 5 楼答案

    我听说过ZeroMQ对于这类场景的好处。它甚至吹嘘在某些情况下比TCP更快。总之,尝试一下肯定不会有什么坏处

  6. # 6 楼答案

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

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

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