首页 \ 问答 \ 如何使用netty通过HTTP流式传输响应(how to stream a response over HTTP with netty)

如何使用netty通过HTTP流式传输响应(how to stream a response over HTTP with netty)

我正在使用Netty 3.6.6,我想向调用者发送一个大的响应。 我无法将响应主体复制到ChannelBuffer中,因为在某些情况下它会非常大。

我正在将服务器从CXF迁移到Netty,以前,我可以使用CXF提供的OutputStream来写入数据。

我原本试图在没有内容的情况下发送响应,然后继续在一系列8k缓冲区中将数据写入Channel。 这失败了,因为客户端似乎得到了原始响应并且看不到任何数据和抱怨。 我尝试将响应设置为chunked,但这似乎没有区别,也没有设置chunked标头,客户端总是看到一个空流。

我看到3.6.6的文件服务器示例,这与我想要做的类似,除了数据不是文件。 我看到了ChunkedStream和NioStream,它似乎接近我需要的,除了它们采用InputStream / ReadableByteChannel而我有一个OutputStream; 我可以尝试使用PipedInput和OutputStreams,但这似乎会引入一个不幸的瓶颈。

我确信有一种方法可以将大量数据流回客户端以响应请求,但我只是没有看到如何操作它,除非我有一个文件。

我也很好奇如果连接保持活动状态,你是如何让客户知道响应是完整的,并且你是流内容,但不知道内容长度。 似乎客户端会在这些情况下永远等待连接关闭。

修改3.6.6中的静态文件服务器示例以删除内容长度标头(只是将其注释掉),指定它是一个分块响应

   response.setChunked(true);
   response.setHeader(Names.TRANSFER_ENCODING, Values.CHUNKED);

然后使用ChunkedNioStream在写入响应后发送文件:

    // Write the initial line and the header.
    ch.write(response);

    final ReadableByteChannel aIn = java.nio.channels.Channels.newChannel(new FileInputStream(file));
    ChannelFuture writeFuture = ch.write(new ChunkedNioStream(aIn));

产生不希望的行为,客户端得到几百个字节,然后停止接收,基本上我在我的应用程序中看到的。 正确的事情似乎只发生在内容长度上,这在我的用例中是不可行的。


I'm using Netty 3.6.6 and I'd like to send a large response back to the caller. I can't copy the response body into a ChannelBuffer as in some cases it will be very large.

I'm migrating a server from CXF to Netty, previously, I could just use the OutputStream provided by CXF to write the data.

I originally tried to just send the response without content, and then continued to write data to the Channel in a series of 8k buffers. This failed as the client seemed to get the original response and see no data and complain. I tried setting the response as chunked, but this didnt seem to make a difference, nor did setting the chunked header, the client always saw an empty stream.

I saw the file server example for 3.6.6, and that's similar to what I want to do, except the data will not be a file. I saw the ChunkedStream & NioStream, which seemed close to what I need, except they take InputStream/ReadableByteChannel whereas I have an OutputStream; I could try using the PipedInput & OutputStreams, but that seems like it would introduce an unfortunate bottleneck.

I'm sure there's a way to stream a lot of data back to the client in response to a request, but I'm just not seeing how to do it unless I have a file.

I am also curious how you let the client know the response is complete if the connection is keep-alive, and you're streaming content, but don't know the content length. Seems like the client would wait forever for the connection to close in those cases.

Modifying the static file server example from 3.6.6 to remove the content-length header (just comment it out), specify that its a chunked response

   response.setChunked(true);
   response.setHeader(Names.TRANSFER_ENCODING, Values.CHUNKED);

and then using ChunkedNioStream to send the file after writing the response:

    // Write the initial line and the header.
    ch.write(response);

    final ReadableByteChannel aIn = java.nio.channels.Channels.newChannel(new FileInputStream(file));
    ChannelFuture writeFuture = ch.write(new ChunkedNioStream(aIn));

Yields the undesired behavior, the client gets a couple hundred bytes and then stop receiving, basically what I'm seeing in my application. The correct thing only seems to happen with a content-length, which is not feasible in my use case.


原文:
更新时间:2022-11-05 22:11

最满意答案

我将对话框创建保持在actionPerformed中,并将以下处理逻辑移动到单独的方法中,然后对该方法进行单元测试。 对话框创建正常,无需对其进行单元测试。


I would keep the dialog creation in actionPerformed, and move the following processing logic into a separate method, and then unit-test only that method. Dialog creation just works, there is no need to unit-test it.

相关问答

更多
  • 有几种方法可以实现您想要的布局。 在这里,我使用GridBagLayout作为内部面板。 我添加颜色只是为了显示组件占用的空间。 包含面板使用GridLayout并添加到滚动窗格。 public class Test extends JFrame { Test() { JPanel main = new JPanel(new GridLayout(0, 1)); for (int i = 0; i < 20; i ++) main.add( ...
  • 我建议您尝试将模型与视图分开。 不要将与应用程序逻辑相关的数据存储在实际的GUI组件中。 存储对数组列表中的组件的引用,然后通过数组列表和各种getText方法访问数据对我来说似乎是个坏主意。 将值存储在表示某个模型的对象中,并让GUI反映模型的状态。 I would suggest that you try to separate the model from the view. Don't store data relevant for the application logic in the actu ...
  • 我认为你能做的最好的事情就是设计你的应用程序,以便能够插入和拔出内容。 所以,插件/模块类型的架构最适合这里。 您可以设计基于组件的模块; 如果应用程序需要模块/插件,请安装,否则不要。 就像我们使用我们的IDE一样,比如Netbeans,Eclipse,IntelliJ。 由于这是一个Swing应用程序,我强烈建议您查看Netbeans平台 。 I think the best you can do is, design your application in a way that you can plu ...
  • 我喜欢你引用的Grouchnikov文章,但我不确定你是否想要更改UI代表。 因为这将是一个不可变对象的视图,我赞成组合而不是继承。 我倾向于将您描述的组件视为渲染器 ,如本例所示 。 您可以添加InputVerifier或DocumwntListener以获得所需的验证。 附录:这是一个使用JFormattedTextField和MaskFormatter的示例。 您需要调整格式掩码以匹配您的比例和长度。 public class TableGrid extends JPanel { priva ...
  • 是的,有几种方法可以做到这一点。 这可以通过将其添加到玻璃窗格来完成,但这通常会阻止您的UI。 我会研究JXLayer ,它允许您包装组件以执行其他绘制作业。 还有一个JBusyComponent依赖于这个库可能会做你想要的。 Yes, there are a few ways of doing this. This could be done by adding it to the glass pane but this will normally block your UI. I would look ...
  • 核心问题可能是上下文之一, LocaHandler可能没有SEHBV或loca_commit按钮的任何上下文,因此您无法引用它(它不在上下文中)。 有几种方法可以解决这个问题...... 你可以... 将loca_commit的引用传递给loca_commit的实例,但除非您打算使用LocaHandler来处理多个动作,否则它实际上没有意义,这意味着...... 你可以... 让LocaHandler只负责做一件事, loca_commit需要它做什么。 这将引导您进入Actions API的领域 怎么样. ...
  • 我将对话框创建保持在actionPerformed中,并将以下处理逻辑移动到单独的方法中,然后仅对该方法进行单元测试。 对话框创建正常,无需对其进行单元测试。 I would keep the dialog creation in actionPerformed, and move the following processing logic into a separate method, and then unit-test only that method. Dialog creation just w ...
  • 您可以直接设置样式,而不是找到要设置样式的元素。 例如,而不是这样做: add(new JLabel("["+ (id+5) + "]: Select an image of maximum dimensions 720 * 350 pixels."), gbc); 你可以做: // Create instruction label JLabel instruction = new JLabel("["+ (id+5) + "]: Select an image of maximum dimensions ...
  • 此代码可用作applet或桌面应用程序。 这里: import java.awt.BorderLayout; import java.awt.Dimension; import javax.swing.*; // public class TutoringCalculator extends JApplet { // The size of an applet is se ...
  • 因此,只要我不调用setVisible方法,就会从创建实例的线程中创建组件 错误。 只要您没有专门创建新Thread或使用实用程序方法(例如SwingUtilities#invoke...方法),就会在当前Thread上调用每个调用,包括setVisible调用。 看起来你认为以某种方式使Swing组件可见会使你的代码切换线程。 不,Swing组件的绘画将在EDT上进行。 正如您所说,Swing不是线程安全的。 这就是为什么你应该在EDT上创建组件,而不是在另一个线程上。 在大多数情况下它可能没有问题,但最 ...

相关文章

更多

最新问答

更多
  • 如何在Laravel 5.2中使用paginate与关系?(How to use paginate with relationships in Laravel 5.2?)
  • linux的常用命令干什么用的
  • 由于有四个新控制器,Auth刀片是否有任何变化?(Are there any changes in Auth blades due to four new controllers?)
  • 如何交换返回集中的行?(How to swap rows in a return set?)
  • 在ios 7中的UITableView部分周围绘制边界线(draw borderline around UITableView section in ios 7)
  • 使用Boost.Spirit Qi和Lex时的空白队长(Whitespace skipper when using Boost.Spirit Qi and Lex)
  • Java中的不可变类(Immutable class in Java)
  • WordPress发布查询(WordPress post query)
  • 如何在关系数据库中存储与IPv6兼容的地址(How to store IPv6-compatible address in a relational database)
  • 是否可以检查对象值的条件并返回密钥?(Is it possible to check the condition of a value of an object and JUST return the key?)
  • GEP分段错误LLVM C ++ API(GEP segmentation fault LLVM C++ API)
  • 绑定属性设置器未被调用(Bound Property Setter not getting Called)
  • linux ubuntu14.04版没有那个文件或目录
  • 如何使用JSF EL表达式在param中迭代变量(How to iterate over variable in param using JSF EL expression)
  • 是否有可能在WPF中的一个单独的进程中隔离一些控件?(Is it possible to isolate some controls in a separate process in WPF?)
  • 使用Python 2.7的MSI安装的默认安装目录是什么?(What is the default installation directory with an MSI install of Python 2.7?)
  • 寻求多次出现的表达式(Seeking for more than one occurrence of an expression)
  • ckeditor config.protectedSource不适用于editor.insertHtml上的html元素属性(ckeditor config.protectedSource dont work for html element attributes on editor.insertHtml)
  • linux只知道文件名,不知道在哪个目录,怎么找到文件所在目录
  • Actionscript:检查字符串是否包含域或子域(Actionscript: check if string contains domain or subdomain)
  • 将CouchDB与AJAX一起使用是否安全?(Is it safe to use CouchDB with AJAX?)
  • 懒惰地初始化AutoMapper(Lazily initializing AutoMapper)
  • 使用hasclass为多个div与一个按钮问题(using hasclass for multiple divs with one button Problems)
  • Windows Phone 7:检查资源是否存在(Windows Phone 7: Check If Resource Exists)
  • 无法在新线程中从FREContext调用getActivity()?(Can't call getActivity() from FREContext in a new thread?)
  • 在Alpine上升级到postgres96(/ usr / bin / pg_dump:没有这样的文件或目录)(Upgrade to postgres96 on Alpine (/usr/bin/pg_dump: No such file or directory))
  • 如何按部门显示报告(How to display a report by Department wise)
  • Facebook墙贴在需要访问令牌密钥后无法正常工作(Facebook wall post not working after access token key required)
  • Javascript - 如何在不擦除输入的情况下更改标签的innerText(Javascript - how to change innerText of label while not wiping out the input)
  • WooCommerce / WordPress - 不显示具有特定标题的产品(WooCommerce/WordPress - Products with specific titles are not displayed)