Mitchapp Mitchapp - 6 months ago 188
Java Question

Send Byte array then String then Byte over socket Java

I need to send a text message to server over Java socket and then to send a byte array and then a string etc...
What i have developed till now is working but the client manage to read only the first string that has been sent.

From the server side: I send byte array using

BufferedOutputStream
, and
PrintWriter
to send string.

The problem is that the client and the server are not synchronized, I mean the server send string then byte array then string without waiting for the client to consume each needed byte.

I mean the scenario is NOT like this:

Server Client
Send String read String
Send byte read byte





But it is like this:

Server Client
Send String
Send byte
Send String
Send byte

read String
read byte
read String
read byte


Something that could be useful is that I know exactly the size of each string and each byte array to be read.

Here is the methods used to send string and byte array respectively:

// Send String to Client
// --------------------------------------------------------------------
public void sendStringToClient (
String response,
PrintWriter output) {
try {
output.print(response);
output.flush();

} catch(Exception e) {
e.printStackTrace();
}
System.out.println("send Seeder String : " + response);
}

// Send Byte to Client
// --------------------------------------------------------------------
public void sendByteToClient (
byte[] response,
BufferedOutputStream output) {
try {
output.write(response, 0, response.length);
//System.out.println("send : " + response);
} catch (IOException e) {
e.printStackTrace();
}
}


Here is the methods used to read string and byte array respectively:

public byte[] readInByte(int size) {

byte[] command = new byte[size];
try {
this.inByte.read(command);
} catch (IOException e) {
e.printStackTrace();
}
return command;
}

public String readInString(int size) {
char[] c = new char[size];
try{
this.inString.read(c, 0, size);
} catch (IOException e) {
e.printStackTrace();
}
return String.valueOf(c);
}

Answer

Something that could be useful is that i know exactly the size of each string to be read and each byte array to be read.

Exactly. That's very common. Basically you length-prefix each message - and you might want to provide more header information than that (is it a string or a byte array message, for example).

You could represent the message length (always in bytes) either as a fixed number of bytes (e.g. 4, assuming you never need more than 4GB messages) or use a 7-bit encoded integer (where you send 7 bits of the length in each byte, and the top bit just indicates whether this is the last byte of the length or not).

Once you've got message lengths, you're basically set - you've effectively divided the stream of data into self-describing blocks. Job done.

(As an aside, I'd avoid using PrintWriter due to its exception-swallowing nature. You won't actually need the writer once you're doing this though, as you'll probably want to convert each String into a byte array anyway, to count its length in bytes before you send it. Remember to specify the encoding!)

Comments