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?
Related
I serialized an object to bytes and send to the server side.
in the server side i got the byte stream but i want to print the object/string i got from the server in order to verify i got it well
server side:
CarServerSocket = new ServerSocket(4441);
System.out.println("Server is ready and waiting for connection from client..\n");
try {
while (true) {
carSocket = CarServerSocket.accept();
System.out.println("Server Connected");
final DataInputStream bytesIR = new DataInputStream(carSocket.getInputStream());
bytesIRLength = bytesIR.readInt();
while (bytesIRLength > 0) {
byte[] messageIn = new byte[bytesIRLength];
bytesIR.readFully(messageIn,0,messageIn.length);
bytesIR.readUTF();
}
}
}catch(EOFException e ){
System.out.println("\ngot all objects from client.\ndisconnecting server...");
CarServerSocket.close();
carSocket.close();
}
}
Cliend side - serialization
objectOut.writeObject(CarList[i]); // converting object to bytes.
objectOut.flush();
objectInBytes = byteOut.toByteArray();
System.out.println("Sending car object #"+i);
dOut.writeInt(objectInBytes.length); // getting object bytes size.
dOut.write(objectInBytes); // sending object in bytes.
I tired to use: toString(), readUTF()... but no luck.
can anyone please advise how i solve it?
Thank you.
You can try to read data from your InputStream with some kind of InputStreamReader, something like this :
CarServerSocket = new ServerSocket(4441);
System.out.println("Server is ready and waiting for connection from client..\n");
try {
while (true) {
carSocket = CarServerSocket.accept();
System.out.println("Server Connected");
StringBuilder yourData = new StringBuilder();
new BufferedReader(new InputStreamReader(carSocket.getInputStream()))
.lines().forEach(stringBuilder::append);
System.out.println(yourData.toString());
}catch(EOFException e ){
System.out.println("\ngot all objects from client.\ndisconnecting server...");
CarServerSocket.close();
carSocket.close();
}
}
objectOut.writeObject(CarList[i]); // converting object to bytes.
objectOut.flush();
objectInBytes = byteOut.toByteArray();
System.out.println("Sending car object #"+i);
dOut.writeInt(objectInBytes.length); // getting object bytes size.
dOut.write(objectInBytes); // sending object in bytes.
All this is completely pointless. It just wastes time and space. Just use ObjectOutputStream.writeObject() directly to the socket at the sender, and ObjectInputStream.readObject() directly from the socket at the receiver.
You need to use ObjectInputStream to deserialize objects. Ok, so your object is entirely contained in a datagram that you've already received. You just need to turn the data buffer into an ObjectInputStream. Coding from the hip, this would be something like ...
try( ByteArrayInputStream bais = new ByteArrayInputStream(messageIn);
ObjectInputStream ois = new ObjectInputStream(bais)) {
Object o = ois.readObject();
}
Edit: Here is some complete code showing this working.
public class ByteStream {
public static void main(String[] args) throws IOException {
Server server = new Server(4441);
new Thread(server).start();
Client client = new Client(4441);
new Thread(client).start();
}
}
class Client implements Runnable {
private final Socket socket;
Client(int port) throws UnknownHostException, IOException {
socket = new Socket("localhost", port);
}
#Override
public void run() {
MyObject send = new MyObject();
send.x = 10;
send.msg = "X = ";
try {
try (DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(send);
oos.flush();
byte[] objectInBytes = baos.toByteArray();
int length = objectInBytes.length;
System.out.println("Client: sending 'objectInBytes' length = " + length);
dos.writeInt(length);
dos.write(objectInBytes);
} finally {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Server implements Runnable {
private final ServerSocket serverSocket;
Server(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
#Override
public void run() {
try {
try (Socket socket = serverSocket.accept();
DataInputStream bytesIR = new DataInputStream(socket.getInputStream())) {
int length = bytesIR.readInt();
byte[] messageIn = new byte[length];
bytesIR.readFully(messageIn);
System.out.println("Server: got datagram length = " + length);
process(messageIn);
} finally {
serverSocket.close();
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
private void process(byte[] messageIn) throws IOException, ClassNotFoundException {
try (ByteArrayInputStream bais = new ByteArrayInputStream(messageIn);
ObjectInputStream ois = new ObjectInputStream(bais)) {
Object o = ois.readObject();
System.out.println(o.getClass() + ": " + o);
}
}
}
class MyObject implements Serializable {
private static final long serialVersionUID = -1478875967217194114L;
double x;
String msg;
public String toString() { return msg + x; }
}
And the output:
Client: sending 'objectInBytes' length = 75
Server: got datagram length = 75
class MyObject: X = 10.0
I am trying to send vector object from UDP server to UDP client in Java.
Sending and Receiving string as an object after serializing has been achieved , but I am unable to send or receive vectors. Below is server ide code.
public class UDPReceive {
public UDPReceive() throws IOException {
try {
int port = Integer.parseInt("1233");
int allReceived=0;
String[] custData=new String[3];
DatagramSocket dsocket = new DatagramSocket(port);
byte[] buffer = new byte[2048];
for(;;) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
dsocket.receive(packet);
String msg = new String(buffer, 0, packet.getLength());
String msg2 = new String(packet.getData());
custData[allReceived]=msg;
allReceived++;
if(allReceived == 3){
System.out.println("All Data Received");
for(int i=0;i<3;i++){
System.out.println(custData[i]);
}
Vector rawData=getTransactions(custData[0],custData[1],custData[2]);
System.out.println("Vectot size "+ rawData.size());
byte[] sendData = new byte[1024];
sendData=(object[])rawData.toArray();
allReceived=0;
}/*if ends here */
}
}
catch (Exception e) {
System.err.println(e);
}
}
Here I want to send back "rawData" variable to client and receive it, and covert it to vector in client side. I tried using byte[] as well, but it didn't work
I suggest you serialize the Vector as an ObjectOutputStream and use ObjectInputStream to get the original Vector.
public static byte[] objectToBytes(Object o) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
return baos.toByteArray();
}
to reverse
public static <T> T bytesToObject(byte[] bytes) throws IOException, ClassNotFoundException {
return (T) new ObjectInputStream(new ByteArrayInputStream(bytes)).readObject();
}
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.
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.
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.