Serialization and Deserialization - Socket Programming - java

I am working on a client server java application, using serialization and deserialization. At first I simply want to send a serialized packet to the server that deserialize it and print it on the screen.
Here is mi Client:
public class Client {
public static void main(String[] args) throws IOException {
int portUDP = Integer.parseInt("6004");
InetAddress host = InetAddress.getByName("127.0.0.1");
DatagramSocket UDPsock = new DatagramSocket();
ByteArrayOutputStream oSt = new ByteArrayOutputStream();
ObjectOutputStream ooSt = new ObjectOutputStream(oSt);
packet pck = new packet(2,1,3,"try");
ooSt.writeObject(pck);
ooSt.flush();
byte[] sendBuf = new byte[30];
sendBuf = oSt.toByteArray();
DatagramPacket payload = new DatagramPacket(sendBuf, sendBuf.length, host, portUDP);
UDPsock.send(payload);
UDPsock.close();
}
}
And here is my Server:
public class Server {
public static void main(String[] args) throws IOException, ClassNotFoundException {
int portUDP = 6004;
DatagramSocket UDPsock = new DatagramSocket(portUDP);
byte[] payload = new byte[30];
DatagramPacket inUDP = new DatagramPacket(payload, payload.length);
UDPsock.receive(inUDP);
ByteArrayInputStream oSt = new ByteArrayInputStream(inUDP.getData());
ObjectInputStream ooSt = new ObjectInputStream(oSt);
packet pck = (packet)ooSt.readObject();
pck.printContents();
UDPsock.close();
}
}
I think that my problem is in the deserialization but I am not able to spot it. Please help me
This are my errors:
Exception in thread "main" java.io.EOFException
at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2353)
at java.io.ObjectInputStream$BlockDataInputStream.readUTFBody(ObjectInputStream.java:3092)
at java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:2892)
at java.io.ObjectInputStream.readUTF(ObjectInputStream.java:1075)
at java.io.ObjectStreamClass.readNonProxy(ObjectStreamClass.java:717)
at java.io.ObjectInputStream.readClassDescriptor(ObjectInputStream.java:833)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1609)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1521)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1781)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
at Server.main(Server.java:23)

byte[] payload = new byte[30];
The problem is here. Serialized streams are far bigger than this. Try 576.
And keep a watch on the size of the outgoing byte array as well. If this gets over 576 you will run into IP fragmentation, which will start to cause datagram loss, and you will eventually run into the path MTU which is generally only 1250-1500 bytes. So you can't serialize large objects.
Also:
ByteArrayInputStream oSt = new ByteArrayInputStream(inUDP.getData());
should be:
ByteArrayInputStream oSt = new ByteArrayInputStream(inUDP.getData(), inUDP.getOffset(), inUDP.getLength());

Related

Udp how to get integer from the server?

i shall implement a UDP-based client/server application and im new in the world of Java. The Server implements a simple request-acknowledge protocol upon the UDP protocol. For a received string identifier (command) with optional parameters the server returns a specified result. For example "thread" returns a random integer number between 1 and 5 and length returns a random integer number between 5 and 25.
The questions is did i do the implementation right and how can i fix my problem (length nr is always between 1 and 5). I think my problem is that in the server class the if statements are not checked. Is there some other way to send a comand to a server i tried here to do it with sending strings then trying to check it with if statements?
and thats my code (Server):
public class server {
public static void main(String[] args) throws IOException, InterruptedException {
DatagramSocket skt;
try {
skt = new DatagramSocket(1252);
byte [] buffer = new byte[1000];
while(true){
DatagramPacket request = new DatagramPacket(buffer, buffer.length);
skt.receive(request);
String arrayMsg = new String(request.getData());
System.out.println(arrayMsg);
//check if the client asks for threadnr
if(arrayMsg.equals("thread")){
int threadnumber = (int) (Math.random()*5)+1;
String threadnum = Integer.toString(threadnumber);
byte [] b = threadnum.getBytes();
DatagramPacket reply = new DatagramPacket(b, b.length, request.getAddress(), request.getPort());
skt.send(reply);;}
//check if the client asks for lengthnr
else if(arrayMsg.equals("length")){
int lengthnumber = (int) (Math.random()*25)+5;
String lengthnum = Integer.toString(lengthnumber);
byte [] b = lengthnum.getBytes();
DatagramPacket reply = new DatagramPacket(b, b.length,request.getAddress(), request.getPort());
skt.send(reply);}
}}
catch (SocketException e) {
System.out.println("UDP Port 9876 is occupied.");
System.exit(1);
}}}
thats my Client:
public class client {
public static void main(String[] args) throws UnknownHostException, IOException {
DatagramSocket skt = new DatagramSocket();
InetAddress host = InetAddress.getByName("localhost");
int serverSocket = 1252;
byte [] senddata = new byte [1000];
byte [] getdata = new byte[1000];
//thread send request
String th = "thread";
senddata = th.getBytes();
DatagramPacket requestth = new DatagramPacket(senddata, senddata.length, host, serverSocket);
skt.send(requestth);
//thread get reply
DatagramPacket replyth = new DatagramPacket ( getdata, getdata.length);
skt.receive(replyth);
String arrayth = new String(replyth.getData());
int threadnr=Integer.parseInt(arrayth.trim()); //convert thread string to int and trim it (whitespace)
System.out.println("Thread received " + threadnr);
//length send request
String lg = "length";
senddata = lg.getBytes();
DatagramPacket requestlg = new DatagramPacket(senddata, senddata.length, host, serverSocket);
skt.send(requestlg);
//length get reply
DatagramPacket replylg = new DatagramPacket ( getdata, getdata.length);
skt.receive(replylg);
String arraylg = new String(replyth.getData());
int lengthnr=Integer.parseInt(arraylg.trim()); //convert thread string to int and trim it (whitespace)
System.out.println("Length received " + lengthnr);
skt.close();
And all i get is something like this:
Thread received 3
Length received 1
(Length should be between 5 and 25 and in my case its never bigger then 5)
The code parses the response from the first message instead of from the last, so you get the random 1-5. I suggest using better names for the variables and you'll spot the problem quicker.

Object undefined in objectoutputstream

I am developing server-client side java program, where I have sliced an jpg image using getSubimage() and saved into int image[][][]
The class below initialises connection with the server and receives an array, however compiler states that readObject() is undifined. Any suggestions how to fix this problem?
Thanks!
public void con() throws IOException {
int port = 7676;
ObjectInputStream inputStream = null;
Socket socket = null;
// try to establish the connection to the server
try {
socket = new Socket(hostName, port);
InputStreamReader is = new InputStreamReader(socket.getInputStream());
int pixels[][][] = new int[20][20][400];
pixels = (int[][][])is.readObject();
}
it must be of type ObjectInputStream, so you should write something like this:
pixels = (int[][][])inputStream.readObject();
where inputStream is type of ObjectInputStream.

Java sending/receiving UDP packet missing data inside

I am implementing a p2p application, in which nodes communicate by UDP packet. The packets read from InputStream are sometime not complete.
Here is my code:
...
protected String key;
protected Identifier messId; //Identifier hold a BigInteger
protected String range;
protected String concat;
....
public ReplicationMessage(DataInput in) throws IOException {
fromStream(in);
}
public void fromStream(DataInput in)
try {
super.fromStream(in);
int length=in.readInt();
byte[] data=new byte[length];
in.readFully(data);
concat = new String(data);
System.out.println("concat: "+concat);
messId = new Identifier(in);
} catch (IOException e) {
e.printStackTrace();
}
}
public void toStream(DataOutput out) {
try {
super.toStream(out);
byte[] data = concat.getBytes();
out.writeInt(data.length);
out.write(data);
messId.toStream(out);
} catch (IOException e) {
e.printStackTrace();
}
}
the read packet sometime is complete, for example
concat: 179136678282544:140737488355328
but sometime is not complete, for example
concat: 179136678282544
concat: 179136678282544
concat: 179136678282544
Can any one tell me what the problem is?
Many thanks
Here are the code for sending/receiving the UDP packet
for sending:
private void sendMessage(int comm, Message message, InetAddress ip, int port)
throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
dout.writeInt(comm);
dout.writeByte(message.code());
message.toStream(dout);
dout.close();
byte[] data = bout.toByteArray();
if (data.length > DATAGRAM_BUFFER_SIZE) {
throw new IOException("Message too big, size="+data.length+
" bytes, max="+DATAGRAM_BUFFER_SIZE+" bytes");
}
DatagramPacket packet = new DatagramPacket(data, data.length, ip, port);
socket.send(packet);
}
For receiving the UDP packet
byte[] buffer = new byte[DATAGRAM_BUFFER_SIZE];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
The sending node and receiving node belonging to one machine. the Buffer receiving packet is set to 10*1024 bytes which is much larger than packet length
Here is code for turning incoming datapacket into stream
ByteArrayInputStream bin = new ByteArrayInputStream(packet.getData(),
packet.getOffset(), packet.getLength());
DataInputStream din = new DataInputStream(bin);
int comm = din.readInt();
byte messCode = din.readByte();
Message message = factory.createMessage(messCode, din);
UDP does not deliver damaged or partial packets. Either you aren't sending all the data or you aren't unpacking it properly. You still haven't posted all the code concerned so it is not possible to say exactly where.

DatagramPacket not transmitting the right message

I'm implementing a client/server application using UDP transmissions. Here is my part of my code :
Client :
InetAddress serverAddress = ...
int serverPort = ...
DatagramSocket socket = new DatagramSocket(9999);
...
String message = "<HELLO>";
byte[] outbuffer = new byte[1000];
outbuffer = message.getBytes();
DatagramPacket packet = new DatagramPacket(outbuffer, outbuffer.length, serverAddress, serverPort);
socket.send(this.packet);
Server :
DatagramSocket serverSocket = new DatagramSocket(9876);
...
byte[] inbuffer = new byte[1000];
DatagramPacket packet = new DatagramPacket(inbuffer, inbuffer.length);
serverSocket.receive(packet);
String response = new String(packet.getData(), 0, packet.getLength());
System.out.println(response);
if("<HELLO>".equals(response)){
System.out.println("OK");
} else {
System.out.println("ERROR");
}
My problem is the following: if I print the response String on the client side that is comming from the client, everything looks fine ("").
But for some reasons when I trie to compare the response coming from the server using .equals or a RegExp it fails !
May be it's related to String encoding but I don't know where and why it fails. Both client and server are running on the same host right now, so it might not be related to JVM differences.
You're currently using the platform default encoding to both encode and decode strings. You should absolutely not do that. Specify the encoding both in the getBytes() call and the constructor call, e.g.
byte[] outBuffer = message.getBytes("UTF-8");
Also note that your current code creates a byte array of length 1000 and then immediately throws it away:
byte[] outbuffer = new byte[1000];
// Byte array created on previous line is now useless!
outbuffer = message.getBytes();
... don't do that.
We can't really tell much more from the code you've given us - if you could produce short but complete programs demonstrating the problem, that would really help.
For debugging, I would suggest you log the contents of the datagram packet you receive, while still in binary. Presumably it's not what you expected, but that doesn't help to show what it was.
EDIT: Here's a pair of short but complete programs which do work:
import java.net.*;
public class Server {
public static void main(String[] args) throws Exception{
DatagramSocket socket = new DatagramSocket(9999);
byte[] inbuffer = new byte[1000];
DatagramPacket packet = new DatagramPacket(inbuffer, inbuffer.length);
socket.receive(packet);
String response = new String(packet.getData(), 0,
packet.getLength(), "UTF-8");
System.out.println(response);
if("<HELLO>".equals(response)){
System.out.println("OK");
} else {
System.out.println("ERROR");
}
}
}
// Client.java
import java.net.*;
public class Client {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket();
byte[] output = "<HELLO>".getBytes("UTF-8");
DatagramPacket packet = new DatagramPacket(output, output.length,
InetAddress.getLocalHost(),
9999);
socket.send(packet);
}
}
You have a variable response and reponse.
I am assuming that they won't be the same and your test should fail.
This is the sort of thing you should be able to see in a debugger.

Sending files through sockets

Hello there im trying to send files using client-server classes in java. For some reason when the method that sends the file is called the socket closes. here is the code :
FileInputStream fIn = new FileInputStream(file);
out = new BufferedOutputStream(clientSocket.getOutputStream());
byte fileContent[] = new byte[(int) file.length()];
fIn.read(fileContent);
for (byte b : fileContent) {
out.write(b);
}
and the code from the client :
FileOutputStream fIn = new FileOutputStream("testing");
BufferedInputStream inAout = new BufferedInputStream(clientSocket.getInputStream());
byte fileContent[] = new byte[1000000];
inAout.read(fileContent);
fIn.write(fileContent);
and the error message i get : SEVERE: null
java.net.SocketException: Socket closed
Im not really experienced with this so if any can help it would be great.
The InputStream.read(byte[]) method returns an int for the number of bytes it actually read. It's not guaranteed to read as many bytes as you requested from the byte array. It'll often return the size of the underlying buffer and you'll have to call it many times.
You can use this to be more efficient by streaming the bytes from the socket to the file instead of buffering the whole byte array in memory. Likewise on the server side you can do the same thing to save memory and be faster than writing a byte at a time.
Here's a working example of a server and client in one that connects to itself to transfer a file:
public class SocketFileExample {
static void server() throws IOException {
ServerSocket ss = new ServerSocket(3434);
Socket socket = ss.accept();
InputStream in = new FileInputStream("send.jpg");
OutputStream out = socket.getOutputStream();
copy(in, out);
out.close();
in.close();
}
static void client() throws IOException {
Socket socket = new Socket("localhost", 3434);
InputStream in = socket.getInputStream();
OutputStream out = new FileOutputStream("recv.jpg");
copy(in, out);
out.close();
in.close();
}
static void copy(InputStream in, OutputStream out) throws IOException {
byte[] buf = new byte[8192];
int len = 0;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
}
public static void main(String[] args) throws IOException {
new Thread() {
public void run() {
try {
server();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
client();
}
}
The reason is pretty simple: The call inAout.read(fileContent) will return after about 4KB of data has been transmitted. That's the input buffer size. So instead of a single huge read, you need a loop and many reads and write as many bytes to fIn as you got from the socket.
Also don't forget to flush the output on the server side (closing will flush it) or some data will be lost.
SEVERE: null java.net.SocketException: Socket closed
That means you've closed the socket yourself and then called another operation that needs it open. For example, closing the socket or its input stream or output stream closes the other stream and the socket. Somewhere or other you are doing that.

Categories