0

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've developed until now is working but the client manages 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);
}
4
  • Can we see the client and server code you are using to achieve this? Commented May 15, 2014 at 18:47
  • @publ1c_stat1c take a look to the code above.thks Commented May 15, 2014 at 19:09
  • @mitchellZ,... i have the similar case like you. SO how do you solve it now? Commented Aug 21, 2014 at 23:33
  • 1
    @gumuruh What i did is sending every thing as a byte array using a separator between string data and byte data and on the client side I read byte by byte and whenever I find a separator I'll know if i have to read the coming data on the buffer as string or byte... btw I tried to send string and byte array over the same socket using serializable object but that was horribly slow(as you may already know). Good luck! Commented Aug 24, 2014 at 12:13

2 Answers 2

3

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!)

Sign up to request clarification or add additional context in comments.

1 Comment

@keyser: That's 2^32, so the largest length you could specify in 4 bytes. You'd need to do some work to handle the fact that Java uses signed ints in order to get above 2GB, of course.
0

I'd be really tempted to convert the data to JSON format and pipe it over http. You get a ton of benefits including ready made http servers and clients for just about every platform on earth along with the JSON interop not to mention all the built in error handling and recovery processing.

The drawbacks would be the additional overhead of http and the JSON encoding. You didn't mention if this was a UDP or TCP socket so that could be an additional drawback if you were trying to go connectionless.

1 Comment

i'm using tcp socket, in fact it is a peer to peer fileshare application, where all peers communication messages are text except the binary date of the file shared(should not be converted to string and have to be send as byte array)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.