【问题标题】:Jersey/Servlet Serverside handling of network failuresJersey/Servlet 服务器端处理网络故障
【发布时间】:2018-03-26 14:11:41
【问题描述】:

-- 编辑:--

重新表述问题。 HTTP 是否知道底层 TCP 连接的状态? TCP 是一种可靠的协议。当服务器向客户端发送数据时,它期望来自该客户端的确认信号。当底层服务器端 TCP 连接无法接收到 ACK 信号时,HTTP 会发生什么?

-- 原始问题:--

我正在尝试解决我们的 HTTP 客户端/服务器应用程序的设计问题。 情况如下:

  • 服务器在 Tomcat 上运行,我们在某种程度上受限于使用 Jersey 或 Servlet 来实现服务器端。
  • 客户端向服务器请求数据,一旦读取就被删除
  • 如果客户没有收到数据,不得删除
  • 无论是否收到数据,客户端都没有确认
  • 客户端实现不能以任何方式更改。
  • 网络连接不稳定,可能会中断很长时间(例如 30 秒),也可能经常中断。

问题:如果客户端发出请求,并且在与服务器断开连接后不久,服务器将无法识别,并且它将删除并发送数据到客户端通过死连接。

理想情况下,我们希望在将数据流刷新到客户端时得到一个 IOException 并相应地处理它:

    try (ServletOutputStream outputStream = httpServletResponse.getOutputStream()) {
        outputStream.write(bytes);
        outputStream.flush();
    } catch (Exception e) {
        // TODO: do something ...
    }

我通过在发送请求后不久终止客户端或通过设置非常低的客户端读取超时值来在本地模拟这一点。在这两种情况下,我都遇到了服务器端异常(使用 bioth Jersey 和 Servlets)。

最后一个测试是通过网络发送请求并在此过程中拉动网络电缆。 不幸的是,我没有得到预期的结果。服务器在未识别中断连接的情况下将数据流式传输回来。

那么,有没有人知道如何在与客户端的连接中断时强制服务器端异常?

任何其他不涉及使用套接字或来自客户端的确认调用的想法?

提前致谢!

【问题讨论】:

    标签: java tomcat jersey servlet-3.0


    【解决方案1】:

    您可以在队列中写入消息以便稍后删除,而不是实时删除文件。如果客户端完全收到文件,删除操作必须检查您写入的数据库。

    【讨论】:

    • 感谢您的快速回复。不幸的是,您的建议需要客户端更改,这是不允许的。
    【解决方案2】:

    我认为除非客户端发送确认消息,否则无法确定数据是否到达客户端。

    唯一的解决方案似乎不是实际删除数据,而是保留它并设置“已删除”标志。但由于我不知道具体的用例,我不确定这是否有帮助......

    【讨论】:

    • 好吧,客户端确实在 TCP 级别发送了一个确认消息。我希望这些信息能向上传播。
    【解决方案3】:

    TCP 是双向协议。

    如果您设置输入流并调用InputStream.read(),如果客户端已断开连接,这应该返回 -1。

    更多细节在这里:

    Java Sockets: check if client is able to receive message from server

    【讨论】:

    • 感谢您的奉献 :) 但是,我面临的问题是在服务器上,而不是在客户端上。我分别尝试使用 OutputStream.push() 和 OutputStream.flush() 以在将输出写入客户端时强制异常。不幸的是,它没有发生。
    • 我明白,但是尝试在服务器上设置一个 InputStream(您不需要从中读取任何实际数据),就好像客户端会发送数据一样。
    • 哦,我明白了,很有趣。我会尽快尝试,不幸的是,我目前正在度过一个很长的假期,我将在 5 月中旬使用我的笔记本电脑。非常感谢,这个建议听起来很有希望!
    猜你喜欢
    • 1970-01-01
    • 2019-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多