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();
}
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
Server side:
public class Server
{
public static final String ALGORITHM = "RSA";
public static final String PRIVATE_KEY_FILE = "C:/Users/mrarsenal10/Desktop/server/key/private.key";
public static final String PUBLIC_KEY_FILE = "C:/Users/mrarsenal10/Desktop/server/key/public.key";
public static void generateKey()
{
try
{
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
keyGen.initialize(1024);
final KeyPair key = keyGen.generateKeyPair();
File privateKeyFile = new File(PRIVATE_KEY_FILE);
File publicKeyFile = new File(PUBLIC_KEY_FILE);
// Create files to store public and private key
if (privateKeyFile.getParentFile() != null) {
privateKeyFile.getParentFile().mkdirs();
}
privateKeyFile.createNewFile();
if (publicKeyFile.getParentFile() != null) {
publicKeyFile.getParentFile().mkdirs();
}
publicKeyFile.createNewFile();
// Saving the Public key in a file
ObjectOutputStream publicKeyOS = new ObjectOutputStream(
new FileOutputStream(publicKeyFile));
publicKeyOS.writeObject(key.getPublic());
publicKeyOS.close();
// Saving the Private key in a file
ObjectOutputStream privateKeyOS = new ObjectOutputStream(
new FileOutputStream(privateKeyFile));
privateKeyOS.writeObject(key.getPrivate());
privateKeyOS.close();
}catch (Exception e)
{
e.printStackTrace();
}
}
public static boolean areKeysPresent()
{
File privateKey = new File(PRIVATE_KEY_FILE);
File publicKey = new File(PUBLIC_KEY_FILE);
if (privateKey.exists() && publicKey.exists())
{
return true;
}
return false;
}
public static String decrypt(byte[] text, PrivateKey key) { // giải mã
byte[] dectyptedText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(ALGORITHM);
// decrypt the text using the private key
cipher.init(Cipher.DECRYPT_MODE, key);
dectyptedText = cipher.doFinal(text);
} catch (Exception ex) {
ex.printStackTrace();
}
return new String(dectyptedText);
}
static void sendFile(Socket sock, String fName) throws FileNotFoundException, IOException
{
File transferFile = new File (fName);
byte [] bytearray = new byte [(int)transferFile.length()];
FileInputStream fin = new FileInputStream(transferFile);
BufferedInputStream bin = new BufferedInputStream(fin);
bin.read(bytearray,0,bytearray.length); // luu vao bytearray
OutputStream os = sock.getOutputStream(); // goi outputstream de
System.out.println("Sending Files...");
os.write(bytearray,0,bytearray.length);
os.flush();
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
if (!areKeysPresent()) {
generateKey();
}
ServerSocket serverSocket = new ServerSocket(15124);
Socket sock = serverSocket.accept();
sendFile(sock, PUBLIC_KEY_FILE);
sendFile(sock, "lich.txt");
sock.close();
}
}
Client side:
public class Client
{
public static final String ALGORITHM = "RSA";
public static final String PUBLIC_KEY_FILE = "C:/Users/mrarsenal10/Desktop/Client/public.key";
static void recvFile(Socket sock, String fName) throws FileNotFoundException, IOException
{
int filesize=1022386;
int bytesRead;
int currentTot = 0;
byte [] bytearray = new byte [filesize];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream(fName);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(bytearray,0,bytearray.length);
currentTot = bytesRead;
do {
bytesRead = is.read(bytearray, currentTot, (bytearray.length-currentTot));
if(bytesRead >= 0) currentTot += bytesRead; }
while(bytesRead > -1);
bos.write(bytearray, 0 , currentTot);
bos.flush();
bos.close();
}
public static byte[] encrypt(String text, PublicKey key) {
byte[] cipherText = null;
try {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(ALGORITHM);
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(text.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return cipherText;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
Socket sock = new Socket("127.0.0.1",15124);
recvFile(sock, "public.key");
recvFile(sock, "lich.txt");
sock.close();
}
}
My problem is here i just can send "public.key" or "lich.txt" from server to client, now i want to send both "public.key" and "lich.txt". Thank for your help.
The problem is with the overall design of both the Server and the Client. On the server side it is sending two different files, but on the Client side it is just a stream of data. There is no distinction between one byte representing data from one file vs the next. So what is probably happening is you are calling recvFile, which receives ALL the data from BOTH files sent by the server. After sending the data, the server closes the connection. (You do this explicitly.) So now, on the client side, you have an invalid socket. However, you try to call recvFile again with the socket thinking that represents the second file. This will lead to the SocketException or more likely OutOfBoundsException you are seeing.
To fix this, you need to add more hand-shaking between the Server and Client. The simplest would be a delimiter representing the end of a file. A better approach would be to append a known-size header to the front of every "message" (aka file) before sending any data which lets the client know the size of the file. Then once the client receives the header it knows exactly how many bytes to read.
For now, to prevent the crash change you're recvFile method to something like this:
byte[] bytearray = new byte[4096];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream(fName);
int bytesRead;
while ((bytesRead = is.read(bytearray)) >= 0) {
if (bytesRead > 0) {
fos.write(bytearray, 0, bytesRead);
}
}
fos.flush();
fos.close();
I have this code from DZone(http://www.dzone.com/links/r/java_custom_serialization_example.html) that serialize/deserialize Java object from/to file.
final class Hello implements Serializable
{
int x = 10;
int y = 20;
public int getX()
{
return x;
}
public int getY()
{
return y;
}
}
public class SerializedComTest {
#AfterClass
public static void tearDownAfterClass() throws Exception {
}
#Test
public void testFile() throws IOException, ClassNotFoundException {
Hello h = new Hello();
FileOutputStream bs = new FileOutputStream("hello.txt"); // ("testfile");
ObjectOutputStream out = new ObjectOutputStream(bs);
out.writeObject(h);
out.flush();
out.close();
Hello h2;
FileInputStream fis = new FileInputStream("hello.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
h2 = (Hello) ois.readObject();
assertTrue(10 == h2.getX());
assertTrue(20 == h2.getY());
}
}
How can I transfer serialized object using Java socket? And also how can I store the serialized/deserialized object to/from a byte array.
This is the code for serialization to/from byte array. I got hints from - Java Serializable Object to Byte Array
#Test
public void testByteArray() throws IOException, ClassNotFoundException, InterruptedException {
Hello h = new Hello();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = new ObjectOutputStream(bos);
out.writeObject(h);
byte b[] = bos.toByteArray();
out.close();
bos.close();
Hello h2;
ByteArrayInputStream bis = new ByteArrayInputStream(b);
ObjectInput in = new ObjectInputStream(bis);
h2 = (Hello) in.readObject();
assertTrue(10 == h2.getX());
assertTrue(20 == h2.getY());
}
How can I transfer serialized object using Java socket?
Wrap its output stream in an ObjectOutputStream.
And also how can I store the serialized/deserialized object to/from a string.
You don't. Serialized objects are binary, and should be stored in byte arrays. A deserialized object is the object itself, not a string.
You don't need those readObject() and writeObject() methods. They don't do anything that wouldn't happen by default.
Like you wrapped your filestream with the objectstream class, you do the same with sockets. You should not "store" a serialized object to a string.
This is the code that works, and I got the hint from http://cyberasylum.janithw.com/object-serialization-over-networks-in-java/.
#Test(timeout = 2000)
public void testStream() throws IOException, ClassNotFoundException, InterruptedException {
PingerThread pinger = new PingerThread(9092);
pinger.start();
String serverAddress = "localhost";
Socket s;
PrintWriter output;
BufferedReader input;
try {
// Client
s = new Socket(serverAddress, 9092);
}
catch (IOException e)
{
// when error, try again
Thread.sleep(500);
s = new Socket(serverAddress, 9092);
}
// send the object over the network
Hello h = new Hello();
ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream());
out.writeObject(h);
out.flush();
ObjectInputStream in = new ObjectInputStream(s.getInputStream());
System.out.println("2");
Hello h2;
h2 = (Hello) in.readObject();
assertTrue(10 == h2.getX());
assertTrue(20 == h2.getY());
}
private class PingerThread extends Thread {
public int portNumber;
public PingerThread(int portNumber) {
super();
this.portNumber = portNumber;
}
#Override
public void run() {
try {
ServerSocket listener = new ServerSocket(this.portNumber);
Socket socket = listener.accept();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
Hello h;
while((h = (Hello) in.readObject()) != null) {
System.out.println("1");
//h = (Hello) in.readObject();
System.out.println(h.getX());
System.out.println(h.getY());
out.writeObject(h);
out.flush();
}
System.out.println("OUT");
socket.close();
listener.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
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.