2013-07-11 55 views
0

我看到一些关于此的帖子,但我仍然无法找到答案。在Java套接字中关闭流的正确方法

这是我的服务器如何与客户端的交互:

public void run() { 
    try { 
     //Read client request 
     InputStream is = server.getInputStream(); 
     byte[] buff = new byte[1024]; 
     int i; 
     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
     while ((i = is.read(buff, 0, buff.length)) != -1) { 
      bos.write(buff, 0, i); 
      System.out.println(i + " bytes readed ("+bos.size()+")"); 
     } 
     is.close(); 
     is = null; 
     //Do something with client request 

     //write response 
     OutputStream os = server.getOutputStream(); 
     os.write("server response".getBytes()); 
     os.flush(); 
     os.close(); 
     os = null; 

    } catch (IOException ioe) { 
     ioe.printStackTrace(); 
    } 
} 

这是客户端:

public void run() { 
     try { 
      InetAddress serverAddr = null; 
      serverAddr = InetAddress.getByName("10.0.2.2"); 
      socket = new Socket(serverAddr, 5000); 

      //Send Request to the server 
      OutputStream os = socket.getOutputStream(); 
      os.write(jsonRequest.toString().getBytes("UTF-8")); 
      os.flush(); 
      os.close(); 
      os = null; 

      //Read Server Response 
      InputStream is = socket.getInputStream(); 
      byte[] buff = new byte[1024]; 
      int i; 
      ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
      while ((i = is.read(buff, 0, buff.length)) != -1) { 
       bos.write(buff, 0, i); 
       System.out.println(i + " bytes readed ("+bos.size()+")"); 
      } 
      is.close(); 
      is = null; 

      //Do something with server response 

     } catch (UnknownHostException uhe) { 
      sendCallbackError(uhe); 
     } catch (IOException ioe) { 
      sendCallbackError(ioe); 
     } 
    } 

正如你可以看到,客户端连接,并发送请求。服务器读取该请求,然后写入客户端将读取的响应。

此代码的问题是客户端中的OutputStream.close()和服务器中的InputStream.close()。正如Javadocs所述,关闭该流将关闭Socket。结果是,当客户端尝试读取服务器响应时,Socket已关闭。

我已经设法通过调用Socket.shutdownInputSocket.shutdownOutput来解决这个问题。但我仍在考虑这是否是这样做的正确方法

作为一个说明,关闭与close()当服务器写入响应或当客户端读取它时不会产生问题(我猜想关闭是在客户端和服务器之间同步)。

所以我的问题是:

  1. 正在使用套接字关闭方法正确的方法是什么?
  2. 我可以保留(发送和阅读从服务器 响应时)
  3. 难道发生与关机关闭会保留一些数据 缓冲区,并且不会被发送与close()关闭最后一个流?
+0

把socket.close()放在finally块中。 –

+0

@PeterLawrey你的意思是不关闭流并关闭套接字?如果是,我想我应该关闭两端的插座,对吧? – momo

+0

您应该关闭套接字,如果您想先刷新输出流,则可能需要先关闭或刷新它。 –

回答

1

你可以做到以下几点:

try{ 
}catch(){ 
}finally{ 
if(is!=null){ 
is.close(); 
} 
if(os!=null){ 
os.close(); 
} 
} 
+0

这是一个简单的例子。 Streams实际上是通过run()方法调用的不同方法创建的。所以我真的无法访问变量,除非我将它们声明为Runnable类的成员变量 – momo

+0

尝试了您的建议。它不适合我,因为如果客户端的OutputStream没有关闭/关闭,服务器会一直读取。也许我应该发送一个终止序列来完成阅读... – momo

0

这段代码的问题是在服务器,客户端和InputStream.close()的OutputStream.close()。正如Javadocs所述,关闭流将关闭Socket。

正确的,但在服务器中的InputStream没有直接连接到Socket:它连接到一些你不知道任何有关。你可以不受惩罚地关闭它,尽管你根本不需要关闭它。如果您喜欢,您可以关闭服务器中的OutputStream:虽然它不是直接连接到Socket,,但它可能会或可能没有任何其他效果,除了冲洗。

要解决您的实际问题,您不需要关闭客户端中的输出流,但需要发送适当的Content-Length:标头。这样服务器就知道从客户端读取多少内容。如果这只是一个GET请求,则内容长度可能为零。你不需要拨打shutdownOutput(),,虽然我想没有什么可以阻止你,并且打电话shutdownInput()对网络没有任何作用,所以再次没有任何意义。

+0

虽然你可能是正确的关于服务器的InputStream,如果我关闭它,然后尝试打开OutputStream,它将失败,并出现Socket Closed IOException。 关于Content-Length,我理解你的意思是保留字节数组的第一个字节来指定消息长度,对不对?我认为这应该是最好的解决方案,因为除非在服务器中关闭()OutputStream或调用socket.shutdownOutput(),否则将不会触发服务器读取(read()!= -1)的方式。最新的工作很好。 – momo

+0

(1)那么不要关闭它。关闭与否与你的问题无关。 (2)不,我指的是HTTP Content-Length标头。看看它。 – EJP

+0

这是一个普通的套接字连接,以简单的旧字节发送JSON,这是唯一实现的协议。我不知道HTTP头如何适合这个实现... – momo