purpose of socket.shutdownOutput()

2020-02-14 02:14发布

问题:

I am using the below code to send data to a tcp server. I am assuming that I need to use socket.shutdownOutput() to properly indicate that the client is done sending the request. Is my assumption correct? If not please let me know the purpose of shutdownOutput(). Also appreciate any further optimizations I can make.

Client

def address = new InetSocketAddress(tcpIpAddress, tcpPort as Integer)
clientSocket = new Socket()
clientSocket.connect(address, FIVE_SECONDS)
clientSocket.setSoTimeout(FIVE_SECONDS)

// default to 4K when writing to the server
BufferedOutputStream outputStream = new BufferedOutputStream(clientSocket.getOutputStream(), 4096)

//encode the data
final byte[] bytes = reqFFF.getBytes("8859_1")
outputStream.write(bytes,0,bytes.length)
outputStream.flush()
clientSocket.shutdownOutput()

Server

ServerSocket welcomeSocket = new ServerSocket(6789)

while(true)
{
    println "ready to accept connections"
    Socket connectionSocket = welcomeSocket.accept()
    println "accepted client req"
    BufferedInputStream inFromClient = new BufferedInputStream(connectionSocket.getInputStream())
    BufferedOutputStream outToClient = new BufferedOutputStream(connectionSocket.getOutputStream())
    ByteArrayOutputStream bos=new ByteArrayOutputStream()

    println "reading data byte by byte"  
    byte b=inFromClient.read()    
    while(b!=-1)
    {        
       bos.write(b)
       b=inFromClient.read()
    }
    String s=bos.toString()

    println("Received request: [" + s +"]")   

    def resp = "InvalidInput"
    if(s=="hit") { resp = "some data" }

    println "Sending resp: ["+resp+"]"

    outToClient.write(resp.getBytes());
    outToClient.flush()
}

回答1:

Socket.shutdownOutput() means that the client is finished sending any data through the TCP connection. It will send the remaining data followed by a termination sequence which will completely close its OUTGOING connection. It is not possible to send any further data, which will also indicate to your program that the request is completely finished. So its recommended if you are sure you don't have to send any more data.

But it's not needed to indicate that the request is finished (you don't have to open/close the output all the time if you have multiple requests), there are other ways.



回答2:

I am using the below code to send data to a tcp server. I am assuming that I need to use socket.shutdownOutput() to properly indicate that the client is done sending the request. Is my assumption correct?

YES Your assumption is correct. And this output ShutDown is known as half close . Using half close the TCP provides the ability for one end of the connection to terminate its output, while still receiving data from the other end. Let me walk you through the effects of socket.shutdownOutput() method :

  1. Locally, the local socket and its input stream behave normally for reading purposes, but for writing purposes the socket and its output stream behave as though the socket had been closed by this end: subsequent writes to the socket will throw an IOException
  2. TCP’s normal connection-termination sequence (a - FIN acknowledged by an ACK) is queued to be sent after any pending data has been sent and acknowledged.
  3. Remotely, the remote socket behaves normally for writing purposes, but for reading purposes the socket behaves as though it had been closed by this end: further reads from the socket return an EOF condition, i.e. a read count of -1 or an EOFException , depending on the method being called.
  4. When the local socket is finally closed, the connection-termination sequence has already been sent, and is not repeated; if the other end has already done a half-close as well, all protocol exchanges on the socket are now complete.

Hence we see that When the EOF is received, that end is assured that the other end has done the output shutdown. And this scenario is perfectly achieved by socket.shutDownOutput() on the other side.

Source: Fundamental Networking in Java, Esmond Pitt