我有一段代码从Servlet请求的输入流中读取POST数据。我正在使用java nio来读取数据。
对于大多数情况和常规数据,代码完全正常。但是,在某些数据较大(content length = 600000
)的情况下,Channel的读取方法似乎因Socket超时错误而失败。此外,这似乎只发生在IE 9上,它适用于Firefox和Chrome。
在调查此问题时,我认为,在使用IE时,发布数据似乎需要比其他浏览器更长的时间来阅读。所以我在代码之前添加了Thread.sleep(400)
,代码也开始适用于IE。
我不想在这段代码之前睡一觉,一个只是一个解决方法,而不是一个正确的解决方案,第二,没有正确的睡眠时间,因为如果数据增加,400可能还不够。
有没有办法告诉频道不要超时或完全取消超时?
以下是正在使用的代码,
ReadableByteChannel channel = Channels.newChannel(inputStream);
byte[] postData = new byte[contentLength];
ByteBuffer buf = ByteBuffer.allocateDirect(contentLength);
int numRead = 0;
int counter = 0;
while (numRead >= 0) {
buf.rewind();
numRead = channel.read(buf);
buf.rewind();
for (int i = 0; i < numRead; i++) {
postData[counter++] = buf.get();
}
}
return postData;
inputStream直接通过request.getInputStream(),内容长度通过request.getContentLength()。
使用的容器是嵌入式模式下的Tomcat 7.0.42。
答案 0 :(得分:0)
您的读取超时太短。增加它。
但是我会抛弃这个NIO代码并直接从输入流中读取。使用DataInputStream.readFully(),它是一行代码。你的NIO代码无论如何都是这样做的,但是以一种非常迂回的方式有几个额外的层。
答案 1 :(得分:0)
如果您可以阅读内容长度标题,则可以根据它增加睡眠时间。这应该至少使您的代码在不同的场景中运行。这当然是一种解决方法,但它似乎是一个坚实的解决方案。或者,您可以set the socket timeout wait to a higher number。但是,这种更改将适用于所有servlet,而且灵活性要低得多。
答案 2 :(得分:0)
因为我找不到任何适合此问题的解决方案。我继续我现有的工作,即睡了一段时间。但问题是我睡了多久,因为我需要睡得更多的数据。并且没有正确的方法知道,因为我无法从内容长度中推导出任何公式,所以睡眠时间是随机的。
所以我可以应用的下一个最好的事情是,我抓住了Socket Timeout Exception,并且在我知道需要的最短时间内睡眠,即400ms。然后再次尝试,在放弃之前设置3次重试的逻辑。到目前为止,这对于增加数据量起了作用。