【问题标题】:Client code "randomly" fails whenever it tries to create GzipInputstream每当尝试创建 GzipInputstream 时,客户端代码“随机”失败
【发布时间】:2010-11-14 06:04:05
【问题描述】:

我的服务器基本上可以满足多个客户的需求。 我基本上是使用 gzip(input/output)stream 来压缩客户端-服务器之间的数据。

许多客户端可以同时向服务器发送请求,因此我有一个线程来满足每个客户端的需求。

现在,我遇到的问题是“随机”某些客户端代码在与服务器建立连接后尝试执行以下操作时会失败。

GZIPInputStream in = new GZIPInputStream(server.getInputStream());

我收到java.io.EOFException

当我说随机时,我的意思是在异常中找不到任何模式。 请求正在正确发送(否则它将不适用于任何客户端请求)。

我已经搜索了很多..但找不到任何东西..:(

关于上述问题的任何指针?

Socket connection= new Socket("localhost",2428);
GZIPOutputStream out = new GZIPOutputStream(connection.getOutputStream());
out.write(url.getBytes());
out.finish();
GZIPInputStream in=null;

try {
    in = new GZIPInputStream(connection.getInputStream(),1024); // Exception raised here
} catch(Exception e) { }

接受新连接并产生新线程的服务器代码。

ServerSocket dsWeb= new ServerSocket(2428);
Socket webClient;
while(true){
webClient = dsWeb.accept();

executor.execute(new ThreadPool()); // each request to be handled by a separate thread 

线程内的代码..

GZIPInputStream inWeb = new GZIPInputStream(webClient.getInputStream());
int c1=0;
byte[] b1 = new byte[100000];
c1=inWeb.read(b1);
//Process the request
GZIPOutputStream outWeb = new GZIPOutputStream(webClient.getOutputStream());
outWeb.write(/* Response */);
outWeb.finish();

这是我得到的异常的堆栈跟踪:

java.io.EOFException at java.util.zip.GZIPInputStream.readUByte(Unknown Source)
at java.util.zip.GZIPInputStream.readUShort(Unknown Source)
at java.util.zip.GZIPInputStream.readHeader(Unknown Source)
at java.util.zip.GZIPInputStream.<init>(Unknown Source)
at java.util.zip.GZIPInputStream.<init>(Unknown Source)
at com.WebServerVNCRequest.doGet(WebServerVNCRequest.java:78) 

【问题讨论】:

  • 当我们实例化 GZIPinputstream 对象时,我假设的问题可能是 tat,如kickjava.com/src/java/util/zip/GZIPInputStream.java.htm 所示,读取流并在读取 -1 时抛出 EOF。因为,有一个单一的服务器输入流供客户端访问,读取为 -1 的字符是由于之前的 read() 操作完成的。以上听起来有道理吗??
  • InputStream.read() 将在流中没有更多数据时返回 -1,因此这仍然是症状而不是根本原因。
  • 如果您删除 gzip 代码会怎样?
  • 发布一个更完整的代码示例...在您的套接字接受循环和在单独线程中运行的代码之间使用webClient 是模糊的。

标签: java tcp java-io gzipinputstream


【解决方案1】:

错误率是多少?难道这些是随机的(偶尔的)网络错误?或者您的服务器偶尔会遇到内部错误?

听起来问题并不在于 GZip 数据本身,而在于偶尔的网络中断。我的猜测是您的服务器偶尔会生成异常并发送无效流,从而导致客户端出现此类错误。或许尝试在服务器上记录所有异常以确保您不会偶尔出现内部故障?

【讨论】:

  • 嗨,我怀疑网络是否是一个问题,因为现在,客户端-服务器应用程序在同一台机器上运行(用于测试目的)。如果我尝试从 BufferedInputStream 读取,那么我发现没有这些错误。我选择压缩数据的主要原因是因为我有大约 130KB 的数据必须在客户端-服务器之间交换,并且使用 BufferedInputStream,我wwas 只能部分阅读.. :( !! 对上述内容的见解?
  • 如果流的类型很重要,那么代码中肯定有一些奇怪的错误。有没有办法发布导致问题的代码?
  • 这是我得到的异常的堆栈跟踪.. java.util.zip.GZIPInputStream.readUByte(Unknown Source) at java.util.zip.GZIPInputStream.readUShort(Unknown Source) 处的 java.io.EOFException ) at java.util.zip.GZIPInputStream.readHeader(Unknown Source) at java.util.zip.GZIPInputStream.(Unknown Source) at java.util.zip.GZIPInputStream.(Unknown Source) at com. WebServerVNCRequest.doGet(WebServerVNCRequest.java:78)
  • TCP 网络中断不会导致 EOFException。 “无效流”也不会。
【解决方案2】:

问题是webClient 没有传递给new ThreadPool()。这只能意味着它是类的实例成员,这会引入线程安全问题。将其设为局部变量并将其显式传递给处理它的Runnable

请注意,您的阅读代码过于乐观。您不会在一次读取中获得整个请求。你必须循环。 100Kb 的缓冲区大小只是浪费空间:即使在解压缩之后,单次读取也不会接近该大小。

【讨论】:

  • 但是,webClient 是一个局部变量。
  • 等等,也许不是?
  • 没有真正的证据,并且代码无法编译,因为它必须是最终的才能提供给new ThreadPool(),如果它是最终的,则无法重新分配。否则这不是真正的代码,在这种情况下问题是徒劳的,应该关闭。
猜你喜欢
  • 2012-05-16
  • 1970-01-01
  • 2019-01-15
  • 1970-01-01
  • 2015-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多