java.io.StreamCorruptedException: invalid stream header: 7371007E - java

I have a client Server application which communicate using objects.
when I send only one object from the client to server all works well.
when I attempt to send several objects one after another on the same stream I get
StreamCorruptedException.
Can some one direct me to the cause of this error?
client write method
private SecMessage[] send(SecMessage[] msgs)
{
SecMessage result[]=new SecMessage[msgs.length];
Socket s=null;
ObjectOutputStream objOut =null;
ObjectInputStream objIn=null;
try
{
s=new Socket("localhost",12345);
objOut=new ObjectOutputStream( s.getOutputStream());
for (SecMessage msg : msgs)
{
objOut.writeObject(msg);
}
objOut.flush();
objIn=new ObjectInputStream(s.getInputStream());
for (int i=0;i<result.length;i++)
result[i]=(SecMessage)objIn.readObject();
}
catch(java.io.IOException e)
{
alert(IO_ERROR_MSG+"\n"+e.getMessage());
}
catch (ClassNotFoundException e)
{
alert(INTERNAL_ERROR+"\n"+e.getMessage());
}
finally
{
try {objIn.close();} catch (IOException e) {}
try {objOut.close();} catch (IOException e) {}
}
return result;
}
server read method
//in is an inputStream Defined in the server
SecMessage rcvdMsgObj;
rcvdMsgObj=(SecMessage)new ObjectInputStream(in).readObject();
return rcvdMsgObj;
and the SecMessage Class is
public class SecMessage implements java.io.Serializable
{
private static final long serialVersionUID = 3940341617988134707L;
private String cmd;
//... nothing interesting here , just a bunch of fields , getter and setters
}

If you are sending multiple objects, it's often simplest to put them some kind of holder/collection like an Object[] or List. It saves you having to explicitly check for end of stream and takes care of transmitting explicitly how many objects are in the stream.
EDIT: Now that I formatted the code, I see you already have the messages in an array. Simply write the array to the object stream, and read the array on the server side.
Your "server read method" is only reading one object. If it is called multiple times, you will get an error since it is trying to open several object streams from the same input stream. This will not work, since all objects were written to the same object stream on the client side, so you have to mirror this arrangement on the server side. That is, use one object input stream and read multiple objects from that.
(The error you get is because the objectOutputStream writes a header, which is expected by objectIutputStream. As you are not writing multiple streams, but simply multiple objects, then the next objectInputStream created on the socket input fails to find a second header, and throws an exception.)
To fix it, create the objectInputStream when you accept the socket connection. Pass this objectInputStream to your server read method and read Object from that.

when I send only one object from the client to server all works well.
when I attempt to send several objects one after another on the same stream I get StreamCorruptedException.
Actually, your client code is writing one object to the server and reading multiple objects from the server. And there is nothing on the server side that is writing the objects that the client is trying to read.

This exception may also occur if you are using Sockets on one side and SSLSockets on the other. Consistency is important.

Related

Read from InputStream causes OutOfMemoryError

My app connects to a Wi-Fi peripheral. I’m using Socket.getInputStream() and Socket.getOutputStream() to read/write data. When the connection is established I store these two streams so that I can reuse them as long as I’m connected. My app sends a command via the OutputStream every second and reads the result from the InputStream by its read() method. After some time I get an "OutOfMemoryError".
Correct me if I’m wrong but I think this is because read() does not remove the read data from the InputStream, right?
My question is: Is it a good practice to store the Streams? Or should I use Socket.getInputStream(), Socket.getOutputStream() every time I send a new command?
It seems not to be a problem with the OutputStream since I can call flush() for that.
What about reset() of InputStream? Does this remove the data for the stream?
Here is the code how I encapsulate my Streams:
#Override
public InputStream getInputStream() throws IOException {
return _Socket.getInputStream();
}
#Override
public OutputStream getOutputStream() throws IOException {
return _Socket.getOutputStream();
}
#Override
public void connect() throws IOException {
try {
SocketAddress socketAddress = new InetSocketAddress(_ip, _port);
_Socket = new Socket(_ip, _port);
} catch (IOException e) {
MyExceptionHandler.appendLog(MyExceptionHandler.exceptionToString(e));
throw e;
}
}
The code for sending and receiving commands comes from this api:
https://github.com/pires/obd-java-api/blob/master/src/main/java/com/github/pires/obd/commands/ObdCommand.java
The exception does also not come immediately. It occurs after ~30 Minutes and a lot of commands sent/received
Correct me if I’m wrong but I think this is because “read()” does not remove the read data from the InputStream, right?
Wrong. If you're running out of memory it's not because of InputStream. You have a bug in your code.
My question is: Is it a good practice to store the Streams?
Yes.
Or should I use “Socket.getInputStream(), Socket.getOutputStream() every time I send a new command?
No.
What about “reset()” of InputStream? Removes this the data for the stream?
No, it does what it says in the Javadoc.
EDIT The code you have linked to is at first inspection a load of rubbish. It never checks for end of stream for example, so when that happens it will read forever, accumulating 0xff bytes and eventually filling up memory. Find something better.

How to setup server-client communication using Telnet via a NetManager class

We're working on a school project where we have to use Telnet (Yes, I know, we shouldn't use it etc., but we have to) to communicate between a server and a client. We have two classes setup, a server and a client, which is a thread. We called our client 'NetManager', it can send and receive messages.
However, we have other classes as well which need to send messages to the server, and handle the output the server returns. We want to do this via the NetManager, instead of setting up a new Thread and socket for each class individually.
However, we do not know how to do this. Ideally we want to have a while(working) { } in our NetManager class which reads the lines the server sends, but we also need to send messages inside the while loop. The messages needs to vary so simply putting them in the while loop won't work. Is there a way to do server-client communication, where multiple classes use the NetManager class to send and receive messages from a server?
I have included a stripped down version of our NetManager class below for reference. This version only reads lines sent by the server, it does not yet send messages (which could be accomplished with out.println();
.
public class NetManager extends Thread {
private BufferedReader in;
private BufferedReader stdIn;
private PrintWriter out;
private String line;
#Override
public void run() {
boolean working = true;
try {
Socket sock = new Socket("localhost", 7789);
out = new PrintWriter(sock.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
while (working) {
try {
line = in.readLine();
System.out.println(line);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Here is a quick scheme I made of the best case scenario:
While I think your design is a good one I also think it may be overly complicated for what you are trying to do. If multiple classes are going to be using the same NetManager instance then you are going to have to implement some sort of locking and/or queuing so only one class tries to access NetManager at a time. Then you will also have to figure out some way to make sure any response received by NetManager gets back to the appropriate caller.
Having said all that, I would have any classes that use NetManager accept an instance of it in the constructor. It would then save a reference to the object and use it as necessary.

socket programming serialized objects

i am having a very weird situation in my code which i dont understand i am sending an object lets say O through a socket then i am changing the value of a variable in the object and sending it again but the second time when i print it on the client side, i am getting the same values as in the 1st object.
client code:
while(true){
try{
order=(Order)ois.readObject();
System.out.println(order);
}
server code:
public void sendOrder(Order o){
try {
out.writeObject(o);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
main method:
Server_Socket ss=new Server_Socket();
ss.sendOrder(o);
o.add(r2);
ss.sendOrder(o);
The value is definitely changing on the serverside before i send it, but i dont understand why on the client side its not showing that r2 added in the object.
The objects are being cached by the ObjectOutputStream. To prevent this, call ObjectOutputStream.reset() after each write. If you are sending simple objects that don't contain other objects, use writeUnshared() instead of writeObject().
The objects are being cached by the IOStreams. To fix this, create a deep clone on the server prior to sending the object back. When the client pulls the object from the stream, it will have a different instance id and it will actually deserialize and instantiate the object on the client side.
Fun stuff.

StreamCorruptedException with heavy data over ObjectInputStream

I have a server-client setup over TCP where the client is sending a number of data sets to the server. The reading/writing uses ObjectInput/OutputStream. I don't have any problems under normal conditions, but when the data flow gets heavy, I get a StreamCorruptedException: invalid type code. The invalid code is different every time. I open the socket once and call a synchronized method to send data from multiple threads.
Client:
socket = new Socket("localhost", sockNum);
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
public synchronized void sendMsg(Message msg){
try{
out.writeObject(security.signObject(msg, privKey));
out.reset();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Server:
ServerSocket server = new ServerSocket(sockNum);
Socket client = server.accept();
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
while(threadActive){
Object line = in.readObject();
handleObject(line);
}
Update: I added out.reset() after each send, but that didn't help the problem. I've also added sleep statments in my loop to decrease the data rate. This gets rid of the error but is not a real solution.
Edit: So it's been a little while since I originally asked this, but I'm running into the problem again. I tried setting up my system so that after every sent message, the thread waits for an "acknowledge" message in return. If the receiving process has the StreamCorruptedException, it sends back a "resend" rather than an ack. This seems to be causing more problems than solutions. Any other ideas?
It sounds like you are writing to the output stream in a multi threaded way i.e. you are writing to it somewhere other than in your example.
BTW: Are you reset()ing the stream regularly to prevent a memory leak?

Forwarding incoming TCP "Commands" to a function?

In Java, how would you set up a socket listener that listened to a socket for a series of bytes that represented a command and on recieving called a method which parsed the incoming data and invoked the appropriate command?
Clarification:
My issue is not with handling the commands (Which might also be error codes or responses to commands from the server) but with creating the socket and listening to it.
More Clarification:
What I want to do is mimic the following line of .Net (C#) code:
_stream.BeginRead(_data,0, _data.Length, new
AsyncCallback(this.StreamEventHandler), _stream);
Where:
_stream is a network stream created from a socket
_data is an array of Byte of length 9
this.StreamHandler is a delegate (function pointer) which get executed when data is read.
I am rewriting a library from C# into Java and the component I am currently writing passes commands to a server over TCPIP but also has to be able to bubble up events/responses to the layer above it.
In C# this seems to be trivial and it's looking less and less so in Java.
Starting from my other answer: The specific part you request is the one that goes into the section: "Magic goes here". It can be done in ohh so many ways, but one is:
final InputStream in = socket.getInputStream();
// This creates a new thread to service the request.
new Thread(new Runnable(){
public void run(){
byte[] retrievedData= new byte[ITEM_LENGTH];
in.read(retrievedData, 0, ITEM_LENGTH);
in.close();
// Here call your delegate or something to process the data
callSomethingWithTheData(retrievedData);
}
}).start();
Have a small main method which sets up the socket and listens for incoming connections. Pass each connection to a worker object (possibly in its own thread).
The worker object should have two APIs: The server and the client. The client API gets a connection and reads data from it, the server API takes a connection and writes data to it.
I like to keep these two in a single class because that makes it much more simple to keep the two in sync. Use a helper class to encode/decode the data for transmission, so you have single point to decide how to transmit integers, commands, options, etc.
If you want to go further, define a command class and write code to serialize that to a socket connection and read it from it. This way, you worker objects just need to declare which command class they handle and the server/client API gets even more simple (at the expense of the command class).
I would
put each command into a class of its own, where each class implements a specific interface (e.g. Command)
create a Map<String,Command> which contains a lookup table from each command string to an instance of the class that implements that command
This should help.
Lesson 1: Socket Communications
The TCP connection provides you with one InputStream and one OutputStream. You could just poll the InputStream continuously for the next command (and its inputs) on a dedicated thread. ByteBuffer.wrap(byte[] array) may be useful in interpreting the bytes as chars, ints, longs, etc. You could also pass objects around using serialization.
Any naive approach most likely will not scale well.
Consider using a REST-approach with a suitable small web-server. Jetty is usually a good choice.
To create an listen to a socket, in a very naive way:
mServerSocket = new ServerSocket(port);
listening = true;
while (listening) {
// This call blocks until a connection is made
Socket socket = serverSocket.accept();
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
// Here you do your magic, reading and writing what you need from the streams
// You would set listening to true if you have some command to close the server
// remotely
out.close();
in.close();
socket.close();
}
Normally it is a good idea to delegate the processing of the input stream to some other thread, so you can answer the next request. Otherwise, you will answer all requests serially.
You also need to define some kind of protocol of what bytes you expect on the input and output streams, but from your question it looks like you already have one.
You could create an enum with one member per command
interface Comamnd {
// whatever you expect all command to know to perform their function
void perform(Context context);
}
enum Commands implements Command{
ACTIONONE() {
void perform(Context context) {
System.out.println("Action One");
}
},
ACTIONTWO() {
void perform(Context context) {
System.out.println("Action Two");
}
}
}
// initialise
DataInputStream in = new DataInputStream(socket.getInputStream());
// in a loop
byte[] retrievedData= new byte[ITEM_LENGTH];
in.readFully(retrievedData);
String command = new String(retrievedData, 0);
Commands.valueOf(command).perform(context);

Categories