如何在Java中完成从套接字读取时可靠地判断?

时间:2010-08-04 18:39:33

标签: java sockets

我们正在与需要我们使用Java套接字与之通信的外部产品集成。我们已经能够从服务器上读取小的响应而没有任何问题,但更大的响应引起了一些令人头疼的问题 我对套接字处理逻辑做了一些更改,现在我们似乎能够在90%的时间内读取大的响应。它偶尔会失败。在这种情况下,失败意味着Java客户端在读取整个响应之前停止从套接字读取。客户认为读取操作已完成,并且正常停止 - 不存在例外或超时 这是当前逻辑的样子:

StringWriter response = new StringWriter();
PrintWriter writer = new PrintWriter(response);

char[] buf = new char[4096];
int readChars;
do {
   readChars = responseBufferedReader.read(buf);
   writer.write(buf, 0, readChars);
} while(readChars != -1 && responseBufferedReader.ready());

responseBufferedReaderBufferedReader缠绕在InputStreamReader Socket InputStream周围的readChars != -1。 此代码大部分时间都有效,但似乎检查ready()Socket不够可靠,无法指示我们是否已从服务器读取所有内容。将读取的字符数与缓冲区大小进行比较也是不可靠的,因为服务器在发送响应时似乎有点慢,导致这些数字不同。
我试过改变字符缓冲区的大小;它有所帮助,但它仍然没有100%的工作时间 在不知道预期响应的大小的情况下,是否有更好,更可靠的方法完全从SocketChannel读取?我一直在研究Socket,但我不确定切换是否有任何好处。
如果有帮助,我们会与服务器建立一个阻止Socket的连接。 {{1}}配置为100秒超时

3 个答案:

答案 0 :(得分:1)

你不应该检查BufferedReader是否准备就绪()告诉你是否已经完成。可能仍在从线路读取字节,而BufferedReader没有任何内容,但Socket尚未关闭。

我不确定BufferedReader会给你什么价值(好吧,它可能有助于你的表现)。我希望以下内容更好:

StringWriter response = new StringWriter();
PrintWriter writer = new PrintWriter(response);

char[] buf = new char[4096];
int readChars;
do {
   readChars = inputStreamReader.read(buf);
   writer.write(buf, 0, readChars);
} while(readChars != -1);

我认为当网络成为瓶颈时你可能会退出循环 - 循环处理结果的速度足够快,以至于Reader还没有准备就绪你认为你已经完成了阅读(尽管你不是。)

答案 1 :(得分:0)

Java blocking socket returning incomplete ByteBuffer

上查看问题的答案

如果网络将邮件分成数据包,您将在读取所有数据包之前退出循环。

答案 2 :(得分:0)

请参阅我对this question的回答。当你从流中读取时,同样的答案适用,并且如果EOF不适用(如本案例中),唯一可靠的方法来知道你何时完成的是以某种方式编码协议中的消息结束 - - 你如何做到这一点取决于你。

编辑:

如果无法修改协议以包含消息边界,则可以调查基于超时的方法。您必须决定在检测到消息结束之前等待多长时间......但是您必须处理在同一个流中获得两条消息的情况。您的代码现在能处理这种情况吗?如果是这样,那么你的答案是缓冲输入并使用该逻辑来检测记录边界。