【问题标题】:Is there a request–response networking API for Java?是否有适用于 Java 的请求-响应网络 API?
【发布时间】:2011-07-01 13:08:37
【问题描述】:

我正在寻找一个简单的 java 库,它可以按以下方式编写代码:

Remote remote = Remote.connect("some_host:1234"); 
Future<String> response = remote.request("hello");
// do something else
String reply = response.get();

它应该基于 tcp/ip 并在网络上使用纯文本消息以与语言无关,以便非 Java 服务器也能够发送/接收请求/响应。

(在告诉我使用普通套接字之前,请记住,在这种情况下,您需要实现包装器来分隔有效负载,关心接收到的消息重新排序,线程处理......这个例子很简单,但并不是那么简单实施很好。)

有没有像这样的现有 API?

PS:...越简单越好!

【问题讨论】:

  • 在打电话给response.get() 之前你做了一些事情很奇怪。您可以稍后再读取套接字;接收到的输入缓冲在套接字中。但是,当您稍后尝试获取答案时,答案很可能甚至都不会出现。
  • 这只是一种以更简单的方式处理它的常见模式。这样,您可以执行多个异步调用,例如Future&lt;String&gt; response1 = remote.request("hello 1"); Future&lt;String&gt; response2 = remote.request("hello 2"); Future&lt;String&gt; response3 = remote.request("hello 3");,并在稍后阶段分别处理它们,也许在完成一些中间数据处理之后。然后对response2.get(); 的调用将根据响应是否到达而阻塞或不阻塞。以这种方式组织代码非常方便,能够将“未来响应”作为对象传递等等。
  • 好的,有道理。我有两个连接类似的东西,我将等待的响应分成两个线程,但如果你有太多的响应等待,那将无法很好地扩展。顺便说一句,我对 java.nio 一无所知,但我认为这就是它的用途。
  • API 在另一端会是什么样子?在这里,您的代码正在发出请求并等待回复;在服务器端,代码必须允许线程等待请求然后发送回复。或者您想要来回进行对称的持续对话吗?
  • 只是一些简单的、面向服务的......就像一个方法 String handleRequest(String msg) 来实现和一个 listen(port, requestHandler)

标签: java networking tcp


【解决方案1】:

看看JMS

【讨论】:

  • 看着:my.execpc.com/~gopalan/jms/jms.html 看起来这不是我真正需要的。此外,通过网络发送的消息似乎不是纯文本。
  • 是的,这就是它被包装/解包的内容。实际通过网络发送的内容又如何呢? ...我怀疑它是纯文本,它可能是某种序列化对象或某种特定格式,包含字符串。还是我弄错了?
  • 嗯...理论上,TCP/IP 数据包内部包含所需的所有信息。 ...即使需要一些“应用程序级”协议,我更喜欢它是纯文本,以便与其他软件(非 java)互操作。
  • JMS 不是协议,它是 API,所以说它是不是纯文本没有意义。
  • 没错,TextMessage的目的就是,呃,封装短信。
【解决方案2】:

使用普通套接字:-)

套接字使用 TCP,而 TCP 负责负载、多个数据包和排序。您仍然需要处理线程,但java.util.concurrent 拥有您所需的一切。不要忘记为您的字符串确定字符编码。

【讨论】:

  • 2个相关问题: 1、基于OutputStream,如何对单条消息的payload进行定界? 2. 如果我发送请求 A,B,C 然后收到对 B,A,C 的响应;如何将响应分配给正确的请求? (我的意思是,输出流将读取 B、A、C)
  • @arnaud 我不明白 Q1。在第二季度,您应该在回复中包含一些关于它正在回答哪个请求的信息。
  • Q1 ...哦,对不起,我的意思是输入流。从套接字读取时,您可以从 InputStream 访问其数据...但是,我看不到您如何分隔消息何时结束和消息何时开始,您得到的只是一个字节序列,即所有消息的串联. Q2:...是的,这就是为什么我在最初的帖子中提到涉及更多工作,因为您还必须管理重新排序
  • 1.现在我明白你对有效载荷的意思了。如果您在同一连接上发送多条消息,那么确实,您必须以一种或另一种方式分隔消息。您可以简单地在消息本身之前发送每条消息的长度,或者使用任何人都无法在消息中使用的分隔符。 2. 只需编写服务器应用程序,以便按照与请求相同的顺序编写答案,或者为每个请求分配一个唯一 ID,并将此 ID 作为响应的一部分发送。
  • 请注意,HTTP 每个连接发送一个请求(除非使用 keep-alive),并且多年来一直运行良好。
【解决方案3】:

TCP 实现通常只给应用程序一个类似流的接口,不能访问单个数据包。 (此外,一些路由器/防火墙可能希望重新打包 TCP 流中的数据,这意味着它们不一定会在发送时到达相同的块中。) 因此我们确实需要在 TCP 之上使用一些打包协议(或者真的在任何流对之上)。

一个非常简单的协议是每个请求/响应一行,但这仅适用于小数据大小(或者您需要以某种方式转义嵌入的换行符)。

如果您希望它更有条理,您可以使用基于 XML 的东西(如 XMPP):每个请求/响应都是一个完整的 XML 元素(包括子元素,如果需要)。

此外,如果您想使用 request–response 方案,您需要说 响应必须与请求的顺序相同(这不允许或至少使服务器端对同一连接上的多个请求的并行处理复杂化),或者您必须定义请求编号,然后响应将以某种方式包含它们相关的请求编号。

例如,HTTP 使用第一种方法(从 1.1 开始 - 在每个连接只有一个请求/响应对之前),而 X 协议使用第二种方法。

对于 HTTP,已经有实现(在客户端和服务器端),它可以完全是纯文本(取决于您发送的数据)。

或者,我们可以直接在基于数据包的协议(如 UDP)上构建我们的协议。但这有 UDP 常见的可靠性问题,我们还需要使用消息编号(将响应与请求相关联)等 - 这可能意味着我们必须再次重新实现一半的 TCP。

所以,抱歉,除了使用 HTTP 之外没有真正的答案。

【讨论】:

    【解决方案4】:

    使用Apache Mina,您可以开发自己的协议,但这可能有点矫枉过正。

    【讨论】:

      【解决方案5】:

      我不知道有任何库可以在套接字上为您提供类似这样的层。 IMAP 协议有一个非常像这样的框架层,但我不知道有什么方法可以独立于 IMAP 的其余部分使用它。这样的库很容易编写,并且可能非常有用,所以如果有人想尝试它,我鼓励他们这样做!

      我能想到的最接近您想要的东西是ZeroMQ in request-reply mode。 ZeroMQ 是用 C 编写的,但有一个 Java binding。这是一个非常好的库——有许多语言的绑定,所以它实际上与语言无关,它确实负责定界有效负载、关心接收到的消息重新排序和线程处理。不过,我不认为它是纯文本的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-01
        • 2020-04-07
        • 1970-01-01
        • 1970-01-01
        • 2018-08-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-14
        相关资源
        最近更新 更多