简体   繁体   English

在Java套接字中关闭流的正确方法

[英]Proper way of closing Streams in Java Sockets

I saw some posts about this but I still can't find an answer. 我看到了一些有关此的帖子,但仍然找不到答案。

This is how my server interacts with the client: 这是我的服务器与客户端交互的方式:

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();
    }
}

And this is the client side: 这是客户端:

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);
        }
    }

As you can see, the client connects and send a request. 如您所见,客户端连接并发送请求。 Server read that request then writes a response that the client will read. 服务器读取该请求,然后编写一个客户端将读取的响应。

The problem with this code is the OutputStream.close() in the client and InputStream.close() in the server. 此代码的问题是客户端中的OutputStream.close()和服务器中的InputStream.close() As stated in the Javadocs, closing the stream will close the Socket . 如Javadocs中所述,关闭流将关闭Socket The result is that when the client tries to read the server response, the Socket is already closed. 结果是,当客户端尝试读取服务器响应时, Socket已经关闭。

I've managed to overcome this by calling Socket.shutdownInput and Socket.shutdownOutput instead. 我设法通过调用Socket.shutdownInputSocket.shutdownOutput克服了这一问题。 However I am still thinking whether this is the proper way of doing it 但是我仍在思考这是否是正确的方法

As a note, closing the streams with close() when server writes the response or when the client reads it doesn't create problems (I would guess the closing is synchronized between client and server). 值得注意的是,当服务器写入响应或客户端读取响应时,使用close()关闭流不会造成问题(我猜关闭是在客户端和服务器之间同步的)。

So my questions are: 所以我的问题是:

  1. Is using the Socket shutdown methods a proper way? 使用Socket关闭方法是否正确?
  2. Can I keep closing the last streams with close() (when sending and reading response from server) 我可以继续使用close()关闭最后一个流吗(从服务器发送和读取响应时)
  3. Could it happen that closing with shutdown would keep some data in the buffer and wouldn't be sent? 难道关闭关闭会在缓冲区中保留一些数据而不会发送?

You can do the following: 您可以执行以下操作:

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

The problem with this code is the OutputStream.close() in the client and InputStream.close() in the server. 此代码的问题是客户端中的OutputStream.close()和服务器中的InputStream.close()。 As stated in the Javadocs, closing the stream will close the Socket. 如Javadocs中所述,关闭流将关闭Socket。

Correct but the InputStream in the server isn't connected directly to a Socket: it is connected to something you don't know anything about. 正确,但是服务器中的InputStream没有直接连接到Socket:它连接到您一无所知的东西。 You can close it with impunity, although again you don't need to close it at all. 您可以随时关闭它,尽管再次不需要完全关闭它。 You can close the OutputStream in the server if you like: although, again, as it isn't connected directly to a Socket, it may or may not have any effect other than flushing. 您可以根据需要在服务器中关闭OutputStream :尽管同样,由于未直接连接到Socket,所以它可能会或可能不会刷新。

To address your actual question, you don't need to close the output stream in the client, but you do need to send an appropriate Content-Length: header. 为了解决您的实际问题,您不需要在客户端中关闭输出流,但是需要发送适当的Content-Length:标头。 That way the server knows how much to read from the client. 这样,服务器便知道要从客户端读取多少内容。 If this is only a GET request the content-length may well be zero. 如果这只是一个GET请求,则内容长度很可能为零。 You don't need to call shutdownOutput(), although I guess there is nothing to stop you, and calling shutdownInput() doesn't do anything to the network anyway so again there is no point to it. 您不需要调用shutdownOutput(),尽管我想没有什么可以阻止您,并且调用shutdownInput()仍然对网络没有任何作用,所以再次没有意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM