Im trying to reconstruct a serialized object and access data from it.
This is how Im sending the object.
Socket socket = new Socket ("localhost", port);
ObjectOutputStream out = new ObjectOutputStream (socket.getOutputStream());
Tester t = new Tester("test");
out.writeObject(t);
out.flush();
And this is how I'm receiving it
// This is how the server is being built
private ServerSocket server;
server = new ServerSocket(port);
newsocket = server.accept();
// And this is how Im actually getting the object
ObjectInputStream input = new ObjectInputStream(newSocket.getInputStream());
Tester obj = (Tester) input.readObject();
System.out.println(obj.getText());
However I only get the following output
[Ljava.lang.StackTraceElement;#237360be
What I was hoping to get was the string I sent in the object "Test". Is there anything Im doing wrong?
My Tester class looks like this
public class Tester implements Serializable {
private String theMessage = "";
public Tester(String message) {
theMessage = message;
}
public String getText() {
return theMessage;
}
}
Try this
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream();
Tester tester0 = new Tester("test")
oos.writeObject(tester0);
oos.close();
System.out.println(tester0.getText());
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
Tester tester = (Tester) ois.readObject();
System.out.println(tester.getText());
If this doesn't work, you may have a bug in your serialization code.
It seems, that you had wrapped code-block of socket listener into try...catch statement, where you are using some logger in catch part in an incorrect way: it prints the stacktrace instead of printing the error cause. This is the most probable explanation, why you receive [Ljava.lang.StackTraceElement;....
Indeed your socket-listener code catches some Exception, which you have to print in an appropriate way.
Related
Let say I have a Server and Client with the following task:
Authenticate (Sending and Receiving authentication code)
Continue Receiving Message
Continue sending Heartbeat message
and I coded it like:
public class Sample{
/** Some code here... **/
//Everything start in authentication() method.
private void authenticate(){
//...
List<Object> msg = new ArrayList<>();
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
msg.add(0, AUTHENTICATION);
msg.add(1, id);
output.writeObject(msg);
output.flush();
output.reset();
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
msg.addAll((Collection<?>) input.readObject());
input.reset();
/** Validate **/
if(AUTHENTICATION_IS_TRUE){
startSendingHeartBeat();
startReceivingMessage();
}
}
private void startSendingHeartBeat(){
//...
List<Object> msg = new ArrayList<>();
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
while(true){
msg.clear();
msg.add(0, "XXX");
msg.add(1, id);
output.writeObject(msg);
output.flush();
output.reset();
}
}
private void startReceivingMessage(){
//...
List<Object> msg = new ArrayList<>();
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
while(true){
msg.clear();
msg.addAll((Collection<?>) input.readObject());
input.reset();
}
}
}
as you can see, I created an ObjectOutputStream and ObjectInputStream for the 3 methods.
Is it bad idea? Should I declare and initialize only one ObjectOutputStream/ObjectInputStream and use it every time I need it?
I haven't run into any problem yet, but I have a doubt.
I've the following code:
public class SenderTask implements Runnable {
private DhtDto dto;
private ObjectOutputStream oos = null;
private Socket socket = null;
public SenderTask(DhtDto dto){
this.dto = dto;
}
#Override
public void run() {
try{
socket = new Socket(InetAddress.getByAddress(new byte[]{10, 0, 2, 2}),dto.sendTo());
oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(dto);
oos.close();
socket.close();
oos.reset();
}catch(IOException e){
Log.e("sender","IOException: ",e);
}
}
}
I'm getting a StreamCorruptedException at the following line:
oos.writeObject(dto);
When I searched, I saw answers saying that I should use only one ObjectOutputStream throughout the lifecycle of socket. But I don't understand what this exactly means. Can someone elaborate on what is the problem here and how to resolve it?
Thanks in advance.
Finally, I've resolved it with some help from a classmate. The idea was to use a BufferedOutputStream in middle of Sockets and ObjectOutputStream. I don't properly know the reason though.
I am going to write a program over TCP/IP and I should send objects by client or by server, It is going right when I want to send or receive strings but when I am trying to read an object:
private Socket client;
public ThreadedClient(Socket client) {
this.client = client;
}
#Override
public void run() {
try {
ObjectInputStream objIn = new ObjectInputStream(client.getInputStream());
while(true){
try {
Object fromClient = objIn.readObject();
} catch (ClassNotFoundException e) {e.printStackTrace();}
}
} catch (IOException e) {e.printStackTrace();}
}
I receive an exception:
java.io.StreamCorruptedException: invalid stream header: 306E6165
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at org.bihe.serverSocket.ThreadedClient.run(Server.java:137)
at java.lang.Thread.run(Unknown Source)
and it refers to this line:
ObjectInputStream objIn = new ObjectInputStream(client.getInputStream());
It is my server code:
ServerSocket ss = new ServerSocket(8800);
while(true){
Socket newClient = ss.accept();
System.out.println(">>>> Client number " + (++counter) + " connected.");
OutputStream outputStream = newClient.getOutputStream();
PrintWriter sender = new PrintWriter(outputStream);
sender.println(true);
sender.flush();
ThreadedClient client = new ThreadedClient(newClient);
clients.add(client);
new Thread(client).start();
Client side code:
sc = new Socket("127.0.0.1", 8800);
InputStream inputStream = sc.getInputStream();
Scanner scanner = new Scanner(inputStream);
boolean s = scanner.nextBoolean();
if(s){
System.out.println("Client connected successfully.");
return true;
}else{
System.out.println("Ohhh, Some problem happened, try again later!");
}
Can anyone explain me what is happening, what is this exception and why I received this exception?
If you want to send object over network you must serialize your objects.
Check this question:
How To send an object over TCP in Java
Java Serialization:
Serialization
You could do it like this:
import java.net.*;
import java.io.*;
class testobject implements Serializable {
int value;
String id;
public testobject(int v, String s ){
this.value=v;
this.id=s;
}
}
public class SimpleServer {
public static void main(String args[]) {
int port = 2002;
try {
ServerSocket ss = new ServerSocket(port);
Socket s = ss.accept();
InputStream is = s.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
testobject to = (testobject)ois.readObject();
if (to!=null){System.out.println(to.id);}
System.out.println((String)ois.readObject());
is.close();
s.close();
ss.close();
}catch(Exception e){System.out.println(e);}
}
}
import java.net.*;
import java.io.*;
public class SimpleClient {
public static void main(String args[]){
try{
Socket s = new Socket("localhost",2002);
OutputStream os = s.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
testobject to = new testobject(1,"object from client");
oos.writeObject(to);
oos.writeObject(new String("another object from the client"));
oos.close();
os.close();
s.close();
}catch(Exception e){System.out.println(e);}
}
}
Just get rid of sending and receiving the Boolean. It's redundant. If there was some problem creating the connection, the socket wouldn't get created: an exception would be thrown instead. You're confusing everything with multiple streams on the same socket. Don't do that.
In your read-object loop, you need to catch EOFException separately, and when you get it, close the socket and exit the loop. If you get any other IOException, log it, close the socket, and exit the loop.
If you'd like to achieve good performance and send object then you definitely should use Google Protobuf
It allows you to define messages in simple .proto files. Then you use bundled compiler to generate Java classes which will be serialized and sent.
Also better idea is to use Netty over plain Java sockets. This prevent you from writing a lot of boilerplate code and define simple serialization/deserialization pipelines. Take a look at user-guide.
I get this exception while trying to send objects over UDP socket in java
java.io.StreamCorruptedException: invalid stream header: 00000000
Here is the code for sender: `
public class Epl_Client implements Serializable{
public static void main(String[] args )
{
try{
ParseMessage pm = new PaseMessage();
DatagramSocket Sock;
Sock = new DatagramSocket();
DatagramPacket Dp;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(4 * 1024);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(lg);
byte[] objectBytes = byteArrayOutputStream.toByteArray();
Dp = new DatagramPacket(objectBytes, objectBytes.length,InetAddress.getByName("localhost"),9876);
Sock.send(Dp);
Sock.close();
}
catch (Exception e){
System.out.println("exception caught" + e);
}
}}
Code for receiver :
public class ClassServer{
public static void main(String[] args){
ParseMessage pm=new ParseMessage();
try{
byte[] recvBuf = new byte[5000];
while(true){
DatagramSocket serverSocket = new DatagramSocket(9876);
ByteArrayInputStream bais = new ByteArrayInputStream(recvBuf);
ObjectInputStream objectInputStream = new ObjectInputStream(bais);
pm= (ParseMessage)objectInputStream.readObject();
System.out.println(pm.message);
bais.close();
objectOutputStream.close();
}
}
catch(Exception e)
{
System.out.println("Exceptiom"+e);
}
}}
And the class
public class ParseMessage implements Serializable{
String message;
public ParseMessage()
{ message="Inavalid";}}
Can anyone help to resolve this error?
You're never actually receiving anything from the socket. Look at your code - you create a DatagramSocket and then never refer to it again. You're always building a ByteArrayInputStream wrapping an array full of zeroes.
You need to call DatagramSocket.receive, and then use the length of the received data when constructing a ByteArrayInputStream. However, you'll need to be certain that you can fit all the data in a single packet. Are you sure you don't want a stream-based protocol?
I'm trying to implement object serialization but stuck at the StreamCorruptedException.
On the server's side:
public class MulticastServer {
public static void main(String[] args) throws java.io.IOException {
new MulticastServerThread().start();
}
}
Which calls:
public class MulticastServerThread extends QuoteServerThread {
boolean moreQuotes=true;
public void run() {
while (moreQuotes) {
try {
byte[] buf = new byte[256];
String dString="Server";
System.out.println(dString);
buf = dString.getBytes();
InetAddress group = InetAddress.getByName("230.0.0.1");
DatagramPacket packet = new DatagramPacket(buf, buf.length,
group, 4446);
socket.send(packet);
ObjectInputStream is=null;
ByteArrayInputStream byteStream = new ByteArrayInputStream(recvBuf);
is = new ObjectInputStream(new BufferedInputStream(byteStream));
Object o1=(Object)is.readObject();
System.out.println(o1.a);
is.close();
socket.close();
}}}}
And Object class on both server and client:
public class Object implements Serializable{
private static final long serialVersionUID=1L;
int a=10;
}
And Client side code:
public class MulticastClient {
public static void main(String[] args) throws IOException {
MulticastSocket socket = new MulticastSocket(4446);
InetAddress address = InetAddress.getByName("230.0.0.1");
socket.joinGroup(address);
Object o1=new Object();
DatagramPacket packet;
for (int i = 0; i < 5; i++) {
byte[] buf = new byte[256];
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String received = new String(packet.getData());
System.out.println("received data" +received);
ObjectOutputStream os = null;
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(15000);
os = new ObjectOutputStream(new BufferedOutputStream(byteStream));
os.flush();
os.writeObject((Object)o1);
System.out.println(o1.a);
os.flush();
}
socket.leaveGroup(address);
socket.close();
}
}
I've done all this:
Put all classes under the same path on both machines
attach breaks and try to find out where the problem is
Can someone please help me? Thanks!
If you are trying to do object serialization over UDP, then you need to serialize the object into the packet's byte array, and read the object from that at the receiving end. There is an old Java World article: Object transport via datagram packets which you might find useful.
It looks like you want to implement a two-directional communication:
server -> send packet
client -> receive packet
client -> send object
server -> receive object
I'm not sure how that's going to work out for you (especially if you have multiple clients).
But at least the following changes will be needed to get anything working:
Your server code is going to need to do a blocking receive call after sending the packet.
The client code is going to need to send the object in a packet.