Java socket InputStream freezes / blocks both client and server

Hello everyone

I recently worked on a tiny program aimed at closing the browser remotely. Basic procedures: Server side:

  • Create a SocketServer to listen on some specific port.
  • Accept the connection and create the corresponding socket object
  • Read an InputStream from the created socket (operation blocked on this)

Client side:

  • Create a socket object to establish a connection to the server.
  • Send a command to close the server-side browser by writing bytes to the OutputStream.
  • Read the server feedback using read () in the InputStream socket (locked during this operation)

Code below:

Server.java

package socket; import java.io.IOException; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.ServerSocket; import java.net.Socket; import java.util.Enumeration; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Server { private static ExecutorService es = Executors.newFixedThreadPool(5); public static void main(String[] args) throws IOException { InetAddress targetAddress = null; NetworkInterface ni = NetworkInterface.getByName("eth2"); System.out.println(ni); Enumeration<InetAddress> inetAddresses = ni.getInetAddresses(); while(inetAddresses.hasMoreElements()) { InetAddress inetAddress = inetAddresses.nextElement(); if(inetAddress.toString().startsWith("/10")) { targetAddress = inetAddress; break; } } ServerSocket sSocket = new ServerSocket(11111, 0, targetAddress); while(true) { System.out.println("Server is running..."); Socket client = sSocket.accept(); System.out.println("Client at: " + client.getRemoteSocketAddress()); es.execute(new ClientRequest(client)); } } } 


ClientRequest.java

 package socket; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class ClientRequest implements Runnable { private Socket client; public ClientRequest(Socket client) { this.client = client; } @Override public void run() { try { System.out.println("Handled by: " + Thread.currentThread().getName()); // get input/output streams for client socket InputStream cis = client.getInputStream(); OutputStream cos = client.getOutputStream(); // buffer size : 1024 ? byte[] buffer = new byte[1024]; int recvSize; int totalRecvSize = 0; while(-1 != (recvSize = cis.read(buffer, totalRecvSize, 1024 - totalRecvSize))) { totalRecvSize += recvSize; } String command = new String(buffer, "utf-8"); System.out.println("Command from client: " + command); String commandNative = CommandMap.getNativeCommand(command.trim()); if(null != commandNative) { Process np = Runtime.getRuntime().exec(commandNative); InputStream is = np.getInputStream(); byte[] bufferProcess = new byte[1024]; int bytesRead; int totalBytesRead = 0; while(-1 != (bytesRead = is.read(bufferProcess, totalBytesRead, 1024 - totalBytesRead))) { totalBytesRead += bytesRead; } // give feed back of process output cos.write(bufferProcess); // close process input stream is.close(); } } catch (IOException e) { e.printStackTrace(); } finally { if(null != client) { try { client.close(); } catch (IOException e) { e.printStackTrace(); } } } } 

and finally Client.java

 package socket; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; import java.nio.charset.Charset; public class Client { private static final int BUF_SIZE = 1024; // feedback message size will not exceed 1024 bytes private static final byte[] BUFFER = new byte[BUF_SIZE]; public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException { Socket socket = new Socket("10.117.37.176", 11111); System.out.println("Connected to Server..."); OutputStream os = socket.getOutputStream(); InputStream is = socket.getInputStream(); String command = "kill ie"; byte[] commandBytes = command.getBytes(Charset.forName("utf-8")); System.out.println("Send: " + command); os.write(commandBytes); System.out.println("After send: " + command); int totalRecv = 0; int recvSize; while(-1 != (recvSize = is.read(BUFFER, totalRecv, BUF_SIZE - totalRecv))) { totalRecv += recvSize; } String feedback = new String(BUFFER, "utf-8"); System.out.println("Feedback: " + feedback); socket.close(); } } 

Repeat problems:

  • The server side cannot read the command, causing read (buffer, offset, len) on the socket's InputStream object. He is blocking.
  • The client side cannot read the feedback, causing it to read (buffer, offset, len) on its socket's InputStream object. He is blocking.
  • But when I comment on the feedback reading operations in Client.java, both the server and the client are working correctly.

I am wondering what are the hidden causes in these codes?
Hope someone can help me, thanks a lot!

+4
source share
2 answers

Your socket read code is read before EOF. you will not get EOF until you close the socket. therefore, your code will never continue.

if you want to send only one command to the socket connection, then close the OutputStream after writing the command (using Socket.shutdownOutput() ).

If you want to send several commands to one socket connection, you will need to find a way to distinguish each command (a simple example here ).

+12
source

You read until EOS appears at both ends, which is a bad choice because you cannot β€œsend” EOS without losing the ability to send additional data over the same connection. You need to reconfigure the application protocol so that you can read the command at the same time without requiring a connection to close to complete it. For example, send strings or a word prefix of length or a self-describing protocol such as XML or Java Serialization Object, or anything you can read through a DataInputStream without relying on an EOFException.

+2
source

All Articles