套接字输入流在最终读取时挂起。 处理这个的最佳方法?

我有点难过如何避免我的sockets挂在阅读上。 这是我的代码:

Socket socket = new Socket("someMachine", 16003); OutputStream outputStream = socket.getOutputStream(); InputStream inputStream = socket.getInputStream(); try { outputStream.write(messageBuffer.toByteArray()); outputStream.flush(); BufferedReader in = new BufferedReader(new InputStreamReader(inputStream)); StringBuffer response = new StringBuffer(); int result; while ((result = in.read()) != -1) { response.append(Character.toChars(result)); System.out.println(result); } System.out.println("Done!"); //never gets printed } catch (...) {} 

上面的代码成功读取了流中的所有数据,但随后挂起。 在网上阅读我期望从服务器(我无法控制)收到-1表示我已经到达流的末尾,但我得到了这个:

 (Lots of data above this point) 57 10 37 37 69 79 70 10 

它然后挂起。 所以,我的问题是:

1)我是否编码错误或服务器响应有问题?

2)如果服务器的响应存在问题(即没有返回-1),我该如何解决这个问题(即挂起时停止读取)。

任何帮助赞赏!

只停止读取会挂起的问题是,这种情况可能发生在两种情况:

1:服务器没有更多要发送的数据

2:服务器已发送更多数据,但由于网络过载,您的客户端尚未收到数据。

而且你只想在第一种情况下真正停止阅读,但你希望在第二种情况下读取阻止。

解决这个问题的方法是制作一个传输协议(标准),它允许服务器告诉客户端它希望发送多少数据。

如果服务器事先知道总数据大小,只需从传输中发送总字节数开始,然后发送数据。 这样客户端就知道它什么时候收到了所有数据。

(或者服务器完成后可以简单地关闭连接。这样read应该失败,但这只有在将来不需要连接时才有效)

我认为当服务器决定停止对话时,你只会获得-1,即关闭其输出流或完全关闭套接字。 此外,该流保持开放以用于潜在的未来传入数据。

我不是Android专家,但这似乎在Android上运行得很好:

  try { telnetClient = new Socket(server, port); } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (telnetClient.isConnected()) { try { InputStream instr = telnetClient.getInputStream(); int buffSize = telnetClient.getReceiveBufferSize(); if (buffSize > 0) { byte[] buff = new byte[buffSize]; int ret_read = instr.read(buff); screen.append(new String(buff, 0, ret_read)); } } catch (IOException e) { screen.append("Exception while reading socket:" + e.getMessage()); } } 

我刚刚遇到了同样的问题。 我通过在创建套接字对象后直接设置超时来解决它… socket.setSoTimeout(10 * 1000);

尝试:

 while ((result = in.read()) != null) { 

我发现这个问题非常强大。 我试图从java执行一个Windows批处理命令,每次尝试从执行的命令读取输入流时进程挂起。

我只能毫不妥协地解决这个问题。

a)通过寻找一条特定的线路,我知道这条线路将从流中发出最终的有用信息。
b)或者在套接字的另一端启动一个新的线程来杀死进程,在这种情况下,等待一段时间后我就是IEDriverServer.exe。

 String[] cmdArray = {"cmd.exe","/c",cmd+ " 2>&1" }; InputStream is = new ProcessBuilder(cmdArray).directory(f).start().getInputStream(); error_buffer = new BufferedReader(new InputStreamReader(is)); int lines=0; while((line=error_buffer.readLine())!=null){ if(line.startsWith("[INFO] Final Memory: ")) { break; } log.debug("Reading cmd Stream "+line); buf.append(line); lines++; }