从Servlet请求输入流读取时的套接字超时

时间:2013-12-11 09:20:10

标签: java sockets servlets inputstream nio

我有一段代码从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。

3 个答案:

答案 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次重试的逻辑。到目前为止,这对于增加数据量起了作用。