java.io exception in ObjectInputStream - java

I have connected my server by gps device. And for reading data I'm using the code
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
that produces the following exception:
java.io.StreamCorruptedException: invalid stream header: 24312C38
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:783)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:280)
at com.tm4u.ServerSocketExample.main(ServerSocketExample.java:34)

The exception suggests that the data stream you're getting from the socket is not a valid object stream. Object streams are intended to read Java objects that were serialized by a Java process. If you're reading data from a GPS device, I doubt that's the type of stream the device is sending.

I'm sure you need to use DataInputStream or BufferedInputStream with InputStreamReader to read data from GPS device.
ObjectInputStream is used read Java objects sent by other application through the ObjectOutputStream. These are less compatible streams. For example: JVM object serialisation protocol must be the same. I doubt that GPS device manufacturer designed this device to be used in this way.

Related

Java won't deserialize object after it is sent through socket stream

I'm trying to create application that will send object through local network using Sockets. When i run server and client code in Intellij Idea they work fine, but when i run server code on one pc and client code on another pc i get errors like java.io.StreamCorruptedException: invalid type code: 00 or java.io.StreamCorruptedException: invalid stream header: 6C69656E
byte[] readBuffer = new byte[4096];
int num = inStream.read(readBuffer); //inStream is socket input stream
ByteArrayInputStream bis = new ByteArrayInputStream(readBuffer);
ObjectInput in = new ObjectInputStream(bis);
Object o = in.readObject(); //this line throws error
The thing is that writing and reading object to socket stream works on server (which is on pc where i created project) but reading from input stream on client (another pc where i copied project) throws error.
Can someone help me with this? I searched everywhere for solution but i can't figure out what is problem with serializing, because it works on same pc but won't on another. Is there any way that i can make this pc independent? This also happens when i create jar files and run it on same pc where it works in Intellij Idea.
It can because that client didnt read message fully.
But the real mistake is that you work with TCP socket like a message protocol transport but TCP is a stream protocol so you have to create your own message protocol on top of TCP.
Why it works fine on local system?
Because transport data between client and server happen too fast in local test and maybe in just one frame so all the message transported in just one IO-call but in internet or a network it doesn't work like you think.
There is 2 way to handle this mistake:
1- Pass SocketInputStream directly to ObjectInputStream instance and let it handle read objects.
2- Create a message protocol for example you can put the size of message in 2 or more first bytes. Then you can workd like this :
Read 2(or more) first bytes and detect size of packet.
Create a buffer for this size and read packet bytes.(make sure you read all of packet data from socket . You can use return value of SocketInputStream.read(byte[]) method to calculate it)
Pass the packet to ObjectInputStream and read object !

Java pattern for subsequent Input & OutputStream

Hello stack overflow world, I've been struggling with the most straight forward and common problem within Java IO, for some time, and now need your help to tackle it.
Check out this piece of code I have in a try block, within a thread.run():
// connect to client socket, and setup own server socket
clientSocket = new Socket(serverHostname, CLIENT_PORT);
//send a test command to download a file
String downloadFileName = "sample.txt";
DataOutputStream dataOutputStream = new DataOutputStream(clientSocket.getOutputStream());
System.out.println("Sending a request to download file : " + downloadFileName + " from user: Arsa node"); //todo: replace with node user later
dataOutputStream.writeUTF("D/sample.txt");
//close socket if host isn't detected anymore, and if socket doesn't become null suddenly
dataOutputStream.flush();
dataOutputStream.close();
System.out.println("****File has been sent****");
in = new DataInputStream(clientSocket.getInputStream());
byte[] retrievedFileData = new byte[8036];
if (in.readInt() > 0) {
System.out.println("Starting file download!");
in.read(retrievedFileData);
System.out.println("File data has been read, converting to file now");
//closing input stream will close socket also
in.close();
}
clientSocket.close();
2 Main questions that have been confusing me to death:
Why does dataOutputStream.close() need to be run for writeUTF to actually send my string to the server socket, I find that when I don't have dos.close(), data isn't retrieved on the other side, further because I close it, I no longer can read from the socket - as it seems the socket connection becomes closed when the Output Stream is previously closed...
What's a better way, following some sort of pattern to do this? For context, all I'm trying to do is write the filename I'm looking to download to my client, then read the response right away, which I expect to be bytes with the file, any error handling I will consider as a part of my development.
Overall, it shouldn't be complicated to write something to a socket, then read and ingest it's response...which doesn't seem to be the case here,
any help would be greatly appreciated! If the ServerSocket code snippet is needed I'm happy to share.
The observed behavior is just a side-effect of close(), as it calls flush() before closing to make sure any buffered data is sent. To solve your problem, you need to call the flush() method instead of closing.
This behavior is not unique to DataOutputStream: a lot of other OutputStream (or Writer) implementations apply buffering, and you will need to flush when you want to ensure the data is sent to the client, written to disk or otherwise processed.
BTW: The DataOutputStream and DataInputStream is for a very specific type of data serialization protocol that is particular to Java. You may want to consider carefully if this is the right protocol to use.

Java InputStream throwing java.io.StreamCorruptedException

I have a problem that I do not quite understand. I have a server socket and a client socket on two separate machines. Server will constantly sends out data in hex and connected client will read the data stream and do some work.
Most of the traffic is happening in that manner. On a few rare occasions, client will send a bytestring to Server. At this point, I am getting
Java.io.StreamCorruptedException at this line:
ObjectInputStream in = new
ObjectInputStream(socketFromClient.getInputStream());
Exception:
java.io.StreamCorruptedException: invalid stream header: 020001B5
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:857)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:349)
at ReadInput.run(ReadInput.java:21)
at java.lang.Thread.run(Thread.java:745)
"020001B5" is exactly the bytestring that client is sending over to server.
I do not understand why I am getting this StreamCorruptedException. My
code logic does not have any "stream header". What is stream header?
I checked javadoc and I could not make out of why this is happening.
Any tip much appreciated.
thanks
-v
Your client is not writing data using ObjectOutputStream: that's why you're seeing this exception. ObjectOutputStream and ObjectInputStream are used for serializing and deserializing Java objects.
Instead of using ObjectInputStream to read data, consider using BufferedReader or a DataInputStream.
See this example for more details.

ObjectInputStream from socket.getInputStream()

I have server
ServerSocket socketListener = new ServerSocket(Config.PORT);
...
client = socketListener.accept();
and client
sock = new Socket("127.0.0.1", Config.PORT);
I want to transfer between them some serialized data using ObjectInputStream and ObjectOutputStream.
When I try to do
ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
Nothing happens neither on the server side nor client side. Everything falls on that line. Both the client and the server is trying to get the input stream from the socket, but it does not work nor the client nor the server.
How do I solve this problem so that I can pass the serialized data between client and server?
As the javadoc says:
Creates an ObjectInputStream that reads from the specified InputStream. A serialization stream header is read from the stream and verified. This constructor will block until the corresponding ObjectOutputStream has written and flushed the header.
So, since both the server and the client start by opening an InputStream, you implemented a deadlock: they both block until the other party has sent the stream header. If you start by opening an ObjectInputStream at client side, you must start by opening an ObjectOutputStream (and flushing immediately if necessary) at server-side (or vice-versa).

Sending variables using sockets

I've started work on a simple newtworking project which creates a new thread for each connection and I'm trying to send multiple things across. What I'm wondering is there an easy way of simple say declaring a variable sending that whole variable to the server and that being sent to other clients. For example if I wanted to send a simple integer array? Basically how would I send an array or even an image across a socket?
Yes, it is possible. What you are looking for is called serialization and can be used to send entire objects through a stream (socket, file, etc.). Have a look at this java socket serialization tutorial.
Check the docs on ObjectOutpuStream and ObjectInputStream.
Basically what you have to do is have any custom type that you want to be serialized implement the Serializable interface:
class MyCustomType implements Serializable {
...
}
This is a marker interface that tells the runtime that this type can be sent over a stream.
Next, once your connections are set up you can obtain the socket input/output stream and write objects using ObjectOutputStream:
MyCustomType obj = new MyCustomType();
ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
oos.writeObject(obj);
oos.flush();
or read them using ObjectInputStream:
ObjectInputStream ois = new ObjectInputStream(client.getOutputStream());
MyCustomType obj = (MyCustomType) ois.readObject();
(client above is a Socket).

Categories