views:

114

answers:

8

I'm using Java sockets for client - server application. I have a situation when sometimes client needs to send a byte array (using byteArrayOutputStream) and sometimes it should send a custom java object. How can I read the information from the input stream on the server side and determine what is in the stream so that I can properly process that?

A: 

What you could do, would be to prepend any data you send with an integer that is used to determine the type.

That way, you could read the first 4 bytes, and then determine what type of data it is.

webdestroya
+2  A: 

In general, I don't believe there is a feature built into Java that allows you to do this.

Instead, consider sending some more information along with each message that explains what type is coming next.

For example, you might prefix your messages with an integer, such that every time you receive a message, you read the first 4 bytes (an integer is 4 bytes) and interpret its value (e.g. 1=byte array, 2=custom Java object, 3=another custom Java object, ...).

You might also consider adding an integer containing the size of the message so that you know when the current message ends and the next message begins.

Jack
If you're going to do a message begin/end flag, it's particularly helpful to also make up an escaping protocol so that if you become desynchronized, you can just look for the message begin marker. If the message begin byte occurs anywhere in the code, transform it into a two byte escape sequence. You also escape the escape character itself, and any other bytes you want to avoid (^S and ^Q, for example, when used over RS-232).
nsayer
I wouldn't suggest a begin/end flag since when serializing Java classes since you might find any character (^S, ^Q, \0, etc) when attempting to serialize a Java class. I am suggesting including the length of the message along with the type of the message. Although, the poster may already know this based on the type of the Java object (perhaps the object will always have exactly the same fields).
Jack
@Jack you do the escaping is to insure that your protocol is completely binary safe despite the fact that you have special begin/end marker bytes (and perhaps bytes you want to entirely avoid). Length bytes don't help you recover if the two endpoints become desynchronized, though admittedly this may not be something you have to worry about over a TCP connection.
nsayer
+1  A: 

You need to define a protocol to indicate what type of data follows. For instance, you could start each transfer with a string or enumerated value. The server would first read this, then read the following data based on the 'header' value.

Adam
+2  A: 

Usually this is to be done by sending a "header" in front of the body containing information about the body. Have a look at for example the HTTP protocol. The HTTP stream exist of a header which is separated from the body by a double newline. The header in turn exist of several fields in name: value format, each separated by a single newline. In this particular case, you would in HTTP have used the Content-Type header to identify the data type of the body.

Since Java and TCP/IP doesn't provide standard facilities for this, you would need to specify and document the format you're going to send over the line in detail so that the other side knows how to handle the stream. You can of course also grab a standard specification. E.g. HTTP or FTP.

BalusC
+1  A: 

First read the data into a byte array on the server. Write your own parsing routine to do nothing more than identify what is in the byte array.

Second perform the full object parsing based on the identification from step one. If the parsing requires passing an inputstream, you can always put the byte array you read in step one into a new ByteArrayInputStream instance.

Erik Hermansen
+2  A: 

There are multiple ways to handle this.

One is Object Serialization, which sends it over with Java's Object(In|Out)putStream. You run into a small problem when knowing when to read the object off the stream though.

Another is to marshal and unmarshal XML. Uses a bit more traffic but is easier to debug and get running. It helps to have a well documented XML schema for this. An advantage here is you can use existing XML libraries for it.

You could try a custom format if you wanted, but it would probably end up being just a sloppy, less verbose version of XML.

glowcoder
The key here is at no point should the author attempt to implement their own object marshalling code.
Jason
@Jason I agree: I can't think of any reason why you'd want to.
glowcoder
+2  A: 

I'm going to get called for overkill for this, but unless you seriously need for this protocol to be economical, you might consider marshalling the data. I mean, without peeking at the data, you can't generally tell the difference between something that's a byte array and something that's something else, since you could conceivably represent everything as a byte array.

You can pretty easily use JAXB to marshall the data to and from XML. And JAXB will even turn byte array objects into hex strings or Base64 for you.

nsayer
this is a neat trick.. but i need this to be as economical as possible...
markovuksanovic
A: 

I think the easiest way is to use an object which contains the data that you will send along with its type information. Then you can just send this object and according to this object's data type property you can extract the data.

jaxvy