Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read all of Inputstream in Server Socket JAVA

I am using Java.net at one of my project. and I wrote a App Server that gets inputStream from a client. But some times my (buffered)InputStream can not get all of OutputStream that client sent to my server. How can I write a wait or some thing like that, that my InputStream gets all of the OutputStream of client?

(My InputStream is not a String)

private Socket clientSocket; private ServerSocket server; private BufferedOutputStream outputS; private BufferedInputStream inputS; private InputStream inBS; private OutputStream outBS;  server = new ServerSocket(30501, 100); clientSocket = server.accept();  public void getStreamFromClient()  {     try {         outBS = clientSocket.getOutputStream();         outputS = new BufferedOutputStream( outBS);         outputS.flush();          inBS = clientSocket.getInputStream();         inputS = new BufferedInputStream( inBS );      } catch (Exception e) {         e.printStackTrace();     } } 

Thanks.

like image 780
A R Avatar asked Nov 07 '13 15:11

A R


People also ask

Which method returns the InputStream attached with the socket?

The getInputStream() method of Java Socket class returns an input stream for the given socket.

How is a socket InputStream and OutputStream created in Java?

In Java, to send data via the socket, you get an OutputStream (1) from it, and write to the OutputStream (you output some data). To read data from the socket, you get its InputStream , and read input from this second stream. You can think of the streams as a pair of one-way pipes connected to a socket on the wall.

How do you read a socket InputStream?

Reading Data From a SocketServerSocket server = new ServerSocket(port); Socket socket = server. accept(); DataInputStream in = new DataInputStream(new BufferedInputStream(socket. getInputStream())); Note that we've chosen to wrap the socket's InputStream in a DataInputStream.


2 Answers

The problem you have is related to TCP streaming nature.

The fact that you sent 100 Bytes (for example) from the server doesn't mean you will read 100 Bytes in the client the first time you read. Maybe the bytes sent from the server arrive in several TCP segments to the client.

You need to implement a loop in which you read until the whole message was received. Let me provide an example with DataInputStream instead of BufferedinputStream. Something very simple to give you just an example.

Let's suppose you know beforehand the server is to send 100 Bytes of data.

In client you need to write:

byte[] messageByte = new byte[1000]; boolean end = false; String dataString = "";  try  {     DataInputStream in = new DataInputStream(clientSocket.getInputStream());      while(!end)     {         int bytesRead = in.read(messageByte);         dataString += new String(messageByte, 0, bytesRead);         if (dataString.length == 100)         {             end = true;         }     }     System.out.println("MESSAGE: " + dataString); } catch (Exception e) {     e.printStackTrace(); } 

Now, typically the data size sent by one node (the server here) is not known beforehand. Then you need to define your own small protocol for the communication between server and client (or any two nodes) communicating with TCP.

The most common and simple is to define TLV: Type, Length, Value. So you define that every message sent form server to client comes with:

  • 1 Byte indicating type (For example, it could also be 2 or whatever).
  • 1 Byte (or whatever) for length of message
  • N Bytes for the value (N is indicated in length).

So you know you have to receive a minimum of 2 Bytes and with the second Byte you know how many following Bytes you need to read.

This is just a suggestion of a possible protocol. You could also get rid of "Type".

So it would be something like:

byte[] messageByte = new byte[1000]; boolean end = false; String dataString = "";  try  {     DataInputStream in = new DataInputStream(clientSocket.getInputStream());     int bytesRead = 0;      messageByte[0] = in.readByte();     messageByte[1] = in.readByte();      int bytesToRead = messageByte[1];      while(!end)     {         bytesRead = in.read(messageByte);         dataString += new String(messageByte, 0, bytesRead);         if (dataString.length == bytesToRead )         {             end = true;         }     }     System.out.println("MESSAGE: " + dataString); } catch (Exception e) {     e.printStackTrace(); } 

The following code compiles and looks better. It assumes the first two bytes providing the length arrive in binary format, in network endianship (big endian). No focus on different encoding types for the rest of the message.

import java.nio.ByteBuffer; import java.io.DataInputStream; import java.net.ServerSocket; import java.net.Socket;  class Test {     public static void main(String[] args)     {         byte[] messageByte = new byte[1000];         boolean end = false;         String dataString = "";          try          {             Socket clientSocket;             ServerSocket server;              server = new ServerSocket(30501, 100);             clientSocket = server.accept();              DataInputStream in = new DataInputStream(clientSocket.getInputStream());             int bytesRead = 0;              messageByte[0] = in.readByte();             messageByte[1] = in.readByte();             ByteBuffer byteBuffer = ByteBuffer.wrap(messageByte, 0, 2);              int bytesToRead = byteBuffer.getShort();             System.out.println("About to read " + bytesToRead + " octets");              //The following code shows in detail how to read from a TCP socket              while(!end)             {                 bytesRead = in.read(messageByte);                 dataString += new String(messageByte, 0, bytesRead);                 if (dataString.length() == bytesToRead )                 {                     end = true;                 }             }              //All the code in the loop can be replaced by these two lines             //in.readFully(messageByte, 0, bytesToRead);             //dataString = new String(messageByte, 0, bytesToRead);              System.out.println("MESSAGE: " + dataString);         }         catch (Exception e)         {             e.printStackTrace();         }     } } 
like image 54
rodolk Avatar answered Sep 18 '22 11:09

rodolk


int c;     String raw = "";     do {         c = inputstream.read();         raw+=(char)c;     } while(inputstream.available()>0); 

InputStream.available() shows the available bytes only after one byte is read, hence do .. while

like image 29
Devashish Priyadarshi Avatar answered Sep 17 '22 11:09

Devashish Priyadarshi