I used the ObjectStream in Socket to transport the class.
The client transports two different data in same class, but the server gets the second data that is same as the first data. It is strange!
Here is my code of client:
public Client()
{
MessageClass messageobject=new MessageClass("login");
messageobject.SetLoginUserInfo("18580409","12345","magicgiant");
try
{
client=new Socket("localhost",1234);
System.out.println("Connected!");
ObjectOutputStream out=new ObjectOutputStream(client.getOutputStream());
out.writeObject(messageobject);
out.flush();
System.out.println(1);
messageobject.inquire=true;
messageobject.SetLoginUserInfo("122131","21312","dfsd");
out.writeObject(messageobject);
out.flush();
System.out.println(2);
}
catch(Exception e)
{
System.out.println(e);
}
}
Here is my server:
public void run()
{
try
{
is=new ObjectInputStream(client.getInputStream());
}
catch (Exception ex)
{
System.out.println(ex);
}
while(true){
try
{
MessageClass messageobject = (MessageClass)is.readObject();
System.out.println(messageobject.GetLoginId()+messageobject.GetLoginPassword());
idSocketItem = new IdSocket(messageobject.GetLoginId(),client,messageobject);
s.idSocketList.addElement(idSocketItem);
}
catch (Exception ex)
{
System.out.println(ex);
}
}
}
The System.out in server should be
1858040912345
12213121312
But the real result is
1858040912345
1858040912345
I have tried to cancel the flush(), but it does not work.
Where is the problem?
The problem is that you're writing the same reference twice:
out.writeObject(messageobject);
out.flush();
System.out.println(1);
messageobject.inquire=true;
messageobject.SetLoginUserInfo("122131","21312","dfsd");
out.writeObject(messageobject);
ObjectOutputStream caches the fact that you've written that reference, and just emits a token to refer to the previous value. Three options to consider:
(Preferred, IMO): Create a new object instead of modifying the existing one
Call writeUnshared() instead of writeObject():
This method is identical to writeObject, except that it always writes the given object as a new, unique object in the stream (as opposed to a back-reference pointing to a previously serialized instance).
Call reset() on the stream after writing the first object:
Reset will disregard the state of any objects already written to the stream. The state is reset to be the same as a new ObjectOutputStream. The current point in the stream is marked as reset so the corresponding ObjectInputStream will be reset at the same point. Objects previously written to the stream will not be refered to as already being in the stream. They will be written to the stream again.
I prefer the first version as logically you've got two different messages - so they should be two different objects.
Additionally, I'd strongly encourage you to start following Java naming conventions, and make all your fields private to encourage encapsulation.
Related
My problem is when it tries to read the object the second time, it throws the exception:
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1356)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at Client.run(BaseStaInstance.java:313)
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1356)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at Client.run(BaseStaInstance.java:313)
The first time I send the exact same object message; however, when I try doing the same thing the second time, it throws the error above. Do I need to re-intialize the readObject() method? I even printed out the message object that is being received by the line below and its exact the same as the first instance where it works ok.
Object buf = myInput.readObject();
I'm assuming there's some problem with appending, but I really have no use for appending. I just want to read a fresh line everytime.
I'd really appreciate some help in fixing this bug. Thank you.
==================================
Before that one line, I'm just creating the input and output objects for the socket in the run() method. The object declaration is outside the run() method in the class:-
#Override
public void run() {
try {
sleep((int) 1 * 8000);
} catch (Exception e) {
e.printStackTrace();
}
try {
//Creating input and output streams to transfer messages to the server
myOutput = new ObjectOutputStream(skt.getOutputStream());
myInput = new ObjectInputStream(skt.getInputStream());
while (true) {
buf = myInput.readObject();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
} catch (Exception e) {
e.printStackTrace();
}
}
}
You're right; I don't close the object. I'm not sure how to do that.
The underlying problem is that you are using a new ObjectOutputStream to write to a stream that you have already used a prior ObjectOutputStream to write to. These streams have headers which are written and read by the respective constructors, so if you create another ObjectOutputStream you will write a new header, which starts with - guess what? - 0xAC, and the existing ObjectInputStream isn't expecting another header at this point so it barfs.
In the Java Forums thread cited by #trashgod, I should have left out the part about 'anew for each object at both ends': that's just wasteful. Use a single OOS and OIS for the life of the socket, and don't use any other streams on the socket.
If you want to forget what you've written, use ObjectOutputStream.reset().
And don't use any other streams or Readers or Writers on the same socket. The object stream APIs can handle all Java primitive datatypes and all Serializable classes.
My problem is when it tries to read the object the second time, it throws the exception:
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1356)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at Client.run(BaseStaInstance.java:313)
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1356)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at Client.run(BaseStaInstance.java:313)
The first time I send the exact same object message; however, when I try doing the same thing the second time, it throws the error above. Do I need to re-intialize the readObject() method? I even printed out the message object that is being received by the line below and its exact the same as the first instance where it works ok.
Object buf = myInput.readObject();
I'm assuming there's some problem with appending, but I really have no use for appending. I just want to read a fresh line everytime.
I'd really appreciate some help in fixing this bug. Thank you.
==================================
Before that one line, I'm just creating the input and output objects for the socket in the run() method. The object declaration is outside the run() method in the class:-
#Override
public void run() {
try {
sleep((int) 1 * 8000);
} catch (Exception e) {
e.printStackTrace();
}
try {
//Creating input and output streams to transfer messages to the server
myOutput = new ObjectOutputStream(skt.getOutputStream());
myInput = new ObjectInputStream(skt.getInputStream());
while (true) {
buf = myInput.readObject();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
} catch (Exception e) {
e.printStackTrace();
}
}
}
You're right; I don't close the object. I'm not sure how to do that.
The underlying problem is that you are using a new ObjectOutputStream to write to a stream that you have already used a prior ObjectOutputStream to write to. These streams have headers which are written and read by the respective constructors, so if you create another ObjectOutputStream you will write a new header, which starts with - guess what? - 0xAC, and the existing ObjectInputStream isn't expecting another header at this point so it barfs.
In the Java Forums thread cited by #trashgod, I should have left out the part about 'anew for each object at both ends': that's just wasteful. Use a single OOS and OIS for the life of the socket, and don't use any other streams on the socket.
If you want to forget what you've written, use ObjectOutputStream.reset().
And don't use any other streams or Readers or Writers on the same socket. The object stream APIs can handle all Java primitive datatypes and all Serializable classes.
My problem is when it tries to read the object the second time, it throws the exception:
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1356)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at Client.run(BaseStaInstance.java:313)
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1356)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at Client.run(BaseStaInstance.java:313)
The first time I send the exact same object message; however, when I try doing the same thing the second time, it throws the error above. Do I need to re-intialize the readObject() method? I even printed out the message object that is being received by the line below and its exact the same as the first instance where it works ok.
Object buf = myInput.readObject();
I'm assuming there's some problem with appending, but I really have no use for appending. I just want to read a fresh line everytime.
I'd really appreciate some help in fixing this bug. Thank you.
==================================
Before that one line, I'm just creating the input and output objects for the socket in the run() method. The object declaration is outside the run() method in the class:-
#Override
public void run() {
try {
sleep((int) 1 * 8000);
} catch (Exception e) {
e.printStackTrace();
}
try {
//Creating input and output streams to transfer messages to the server
myOutput = new ObjectOutputStream(skt.getOutputStream());
myInput = new ObjectInputStream(skt.getInputStream());
while (true) {
buf = myInput.readObject();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
} catch (Exception e) {
e.printStackTrace();
}
}
}
You're right; I don't close the object. I'm not sure how to do that.
The underlying problem is that you are using a new ObjectOutputStream to write to a stream that you have already used a prior ObjectOutputStream to write to. These streams have headers which are written and read by the respective constructors, so if you create another ObjectOutputStream you will write a new header, which starts with - guess what? - 0xAC, and the existing ObjectInputStream isn't expecting another header at this point so it barfs.
In the Java Forums thread cited by #trashgod, I should have left out the part about 'anew for each object at both ends': that's just wasteful. Use a single OOS and OIS for the life of the socket, and don't use any other streams on the socket.
If you want to forget what you've written, use ObjectOutputStream.reset().
And don't use any other streams or Readers or Writers on the same socket. The object stream APIs can handle all Java primitive datatypes and all Serializable classes.
My problem is when it tries to read the object the second time, it throws the exception:
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1356)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at Client.run(BaseStaInstance.java:313)
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1356)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
at Client.run(BaseStaInstance.java:313)
The first time I send the exact same object message; however, when I try doing the same thing the second time, it throws the error above. Do I need to re-intialize the readObject() method? I even printed out the message object that is being received by the line below and its exact the same as the first instance where it works ok.
Object buf = myInput.readObject();
I'm assuming there's some problem with appending, but I really have no use for appending. I just want to read a fresh line everytime.
I'd really appreciate some help in fixing this bug. Thank you.
==================================
Before that one line, I'm just creating the input and output objects for the socket in the run() method. The object declaration is outside the run() method in the class:-
#Override
public void run() {
try {
sleep((int) 1 * 8000);
} catch (Exception e) {
e.printStackTrace();
}
try {
//Creating input and output streams to transfer messages to the server
myOutput = new ObjectOutputStream(skt.getOutputStream());
myInput = new ObjectInputStream(skt.getInputStream());
while (true) {
buf = myInput.readObject();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
} catch (Exception e) {
e.printStackTrace();
}
}
}
You're right; I don't close the object. I'm not sure how to do that.
The underlying problem is that you are using a new ObjectOutputStream to write to a stream that you have already used a prior ObjectOutputStream to write to. These streams have headers which are written and read by the respective constructors, so if you create another ObjectOutputStream you will write a new header, which starts with - guess what? - 0xAC, and the existing ObjectInputStream isn't expecting another header at this point so it barfs.
In the Java Forums thread cited by #trashgod, I should have left out the part about 'anew for each object at both ends': that's just wasteful. Use a single OOS and OIS for the life of the socket, and don't use any other streams on the socket.
If you want to forget what you've written, use ObjectOutputStream.reset().
And don't use any other streams or Readers or Writers on the same socket. The object stream APIs can handle all Java primitive datatypes and all Serializable classes.
I want to send an array of double as an object via ObjectOutputStream that uses a socket for outputStream. In the receiving side I read repetitious objects all the same! Maybe the assignment of method readObject doesn't perform it's task.
I'm trying to update dobArray and write it to the socket output stream. dobArray is updated by another thread. It does it's task well, because I tested it. here is my code:
sending side:
objectStream = new ObjectOutputStream(dataFlow.getOutputStream());
while(busy){
try {
// dobArray is updated in another thread
objectStream.writeObject( dobArray);
} catch (IOException e) {
e.printStackTrace();
}
}
receiving side:
objectInputStream = new ObjectInputStream(
mainServer.dataFlow.getInputStream());
while (busy){
try {
DobArray dobarray =
(DobArray) objectInputStream.readObject()
writeToFile(dobarray);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
regards
sajad
ObjectOutputStream is buffered. If you don't flush() the stream it can wait, buffered indefinitely.
When you pass a reference to an object it passes the value of that object only once. After that it only passes an object tag. This prevents recursive objects being serialized endlessly. However, if you pass a mutable object, on the first copy is sent.
Only way around this is to call reset(), but the simplest solution is to use writeUnshared() which sends the object every time.
while(busy)
You are in a loop, repeatedly sending this data? Why is this here and when is busy set to false?
You should only call writeObject one time.