I am trying to process an object on the server with UDP. I serialize it, send it to the server. On the server, I deserialize, modify, then serialize back to send back to the client. On the client I get it, and when I try to readObject () I get an EOF exception. Please help, what could be the problem? I didn't find the answer anywhere.
This is client:
public class Client {
public static void main(String[] args) {
Help help = new Help("WTF");
try {
byte[] objByteArray = serialize(help);
DatagramSocket ds = new DatagramSocket();
InetAddress host = InetAddress.getLocalHost();
int port = 6789;
int objLength = objByteArray.length;
DatagramPacket dp = new DatagramPacket(objByteArray, objLength, host, port);
ds.send(dp);
dp = new DatagramPacket(objByteArray, objLength);
ds.receive(dp);
byte[] new_arr = objByteArray;
Help deserializedObj = (Help) deserialize(objByteArray);
System.out.println(deserializedObj.getData());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SocketException e) {
throw new RuntimeException(e);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
}
}
public static byte[] serialize(Object obj) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)){
oos.writeObject(obj);
byte[] objByteArray = baos.toByteArray();
return objByteArray;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static Object deserialize(byte[] arr) throws IOException, ClassNotFoundException {
Object result = null;
try (ByteArrayInputStream bais = new ByteArrayInputStream(arr);
ObjectInputStream ois = new ObjectInputStream(bais)){
result = ois.readObject();
}
catch (IOException e){
}
return result;
}
}
And this is Server:
public class Server {
public static void main(String[] args) throws IOException {
String filepath = System.getProperty("user.dir") + "\\src\\Server\\Data\\Collection.json";
CollectionManager.setFilePath(filepath);
byte[] arr = new byte[100000];
DatagramSocket ds = new DatagramSocket(6789);
DatagramPacket dp = new DatagramPacket(arr, arr.length);
ds.receive(dp);
try {
Help deserializedObj = (Help) deserialize(arr);
deserializedObj.setData("Server finished work!");
System.out.println("Done!");
byte[] serializedObj = serialize(deserializedObj);
InetAddress host = dp.getAddress();
int port = dp.getPort();
dp = new DatagramPacket(serializedObj, serializedObj.length, host, port);
ds.send(dp);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public static byte[] serialize(Object obj) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)){
oos.writeObject(obj);
byte[] objByteArray = baos.toByteArray();
return objByteArray;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static Object deserialize(byte[] arr) throws IOException, ClassNotFoundException {
Object result = null;
try (ByteArrayInputStream bais = new ByteArrayInputStream(arr);
ObjectInputStream ois = new ObjectInputStream(bais)){
result = ois.readObject();
}
catch (IOException e){
}
return result;
}
}
And also the classes:
public class Help extends Command implements Serializable {
public Help(String name){
super.setName(name);
}
private String data;
public void setData(String s){
data = s;
}
public String getData(){
return data;
}
#Override
public void execute() {
}
}
The problem was that the packet sent from the server is larger than the original one, therefore, on the client, we must receive data into the buffer with a margin, and from there try to read the data.
This is an edited Client code:
byte[] buffer = new byte[1024];
dp = new DatagramPacket(buffer, buffer.length);
ds.receive(dp);
Related
I'm developing a real time application in Java with communication between one server and one client with UDP socket.
It worked fine when i send and receive string but when i tried to receive a custom class Message. i got this error :java.io.StreamCorruptedException: invalid stream header: 00000000
at line message = (Message) objectInputStream.readObject(); in the "receiveMessage" function
I don't know why i have this error.
My Message class:
public class Message implements Serializable {
private static final long serialVersionUID = 1L;
private TypeMessage typeMessage;
private int seedMap;
public Message(TypeMessage typeMessage) {
this.typeMessage = typeMessage;
}
public TypeMessage getTypeMessage() {
return typeMessage;
}
public void setTypeMessage(TypeMessage typeMessage) {
this.typeMessage = typeMessage;
}
public int getSeedMap() {
return seedMap;
}
public void setSeedMap(int seedMap) {
this.seedMap = seedMap;
}
My send function used by the client and the server:
public final static void sendMessage(Message message, DatagramChannel socketSender, InetSocketAddress addressRecever) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos;
oos = new ObjectOutputStream(baos);
oos.writeObject(message);
oos.flush();
byte[] data = baos.toByteArray();
ByteBuffer bufferSocket = ByteBuffer.allocate(SIZE_BUFFER);
bufferSocket.put(data);
socketSender.send(bufferSocket, addressRecever);
} catch (Exception e) {
System.out.println(e);
}
}
My receive function used by the server and the client:
public final static Message receiveMessage(DatagramChannel socketRecever, SocketAddress socketSender) {
Message message = null;
try {
ByteBuffer bufferSocket = ByteBuffer.allocate(SIZE_BUFFER);
bufferSocket.clear();
socketSender = socketRecever.receive(bufferSocket);
if(socketSender != null) {
bufferSocket.flip();
byte[] bytes = new byte[bufferSocket.limit()];
bufferSocket.get(bytes);
ByteArrayInputStream bytesStream = new ByteArrayInputStream(bytes);
ObjectInputStream objectInputStream = new ObjectInputStream(bytesStream);
message = (Message) objectInputStream.readObject();
}
} catch (Exception e) {
System.out.println(e);
e.printStackTrace();
}
return message;
}
Thanks in advance for help
I'm writing a program where the server draws a shape in its app and the client can see that shape in its own app. I thought about converting the object to a byte array but it didn't do anything.
The server code
private void sendShape(Graphics drawedShape) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(drawedShape);
oos.flush();
byte[] yourBytes = bos.toByteArray();
/*oos.writeObject(drawedShape);
oos.flush();
dispMessage("\n Teacher:" + "Shape sent!");*/
} catch (IOException e) {
jta.append("\nError");
}
}
The client code
private void processConn() throws IOException {
send("Successful");
setButtonEnabled(true);
String msg = "";
Graphics object;
ByteArrayInputStream bis = null;
do {
try
{
Object incomingObject = ois.readObject();
if(incomingObject.getClass().toString().contains("Graphics"))
{
try {
ois = new ObjectInputStream(bis);
Object o = ois.readObject();
/*object = (Graphics) ois.readObject();
dispMessage("\n" + object);*/
}finally {
try {
if (ois != null) {
ois.close();
}
} catch (IOException ex) {
}
}
}
I want to send some objects using network. My network I made it using DatagramSocket, DatagramPacket, ByteArrayInputStream, ObjectInputStream, ByteArrayOutputStream and ObjectOutputStream.
When I was trying to send an object using network I got java.io.EOFException and when I handled this exception using try and catch I lost my object.
Server Side
public class GameServer extends Thread {
private DatagramSocket socket;
private DatagramPacket packet;
private byte[] data;
private ByteArrayInputStream bais;
private ObjectInputStream ois;
private ByteArrayOutputStream baos;
private ObjectOutputStream oos;
private Game game;
public GameServer() {
try {
this.socket = new DatagramSocket(1331);
}
catch (SocketException e) {
e.printStackTrace();
}
start();
}
#Override
public void run() {
while (true) {
data = new byte[6400];
packet = new DatagramPacket(data, data.length);
Object object = receive();
if (object instanceof String) {
String message = (String) object;
System.out.println("CLIENT [ " + packet.getAddress().getHostAddress() + " : " + packet.getPort() + " ] >> " + message.trim());
if (message.equalsIgnoreCase("start")) {
game = new Game("Tankies", 1200, 700);
sendObject(game);
}
}
else if (object instanceof State) {
System.out.println("got state");
}
else if (object instanceof Player)
System.out.println("hi player");
}
}
private Object receive() {
bais = new ByteArrayInputStream(data);
try {
socket.receive(packet);
ois = new ObjectInputStream(new BufferedInputStream(bais));
return ois.readObject();
} catch (EOFException e) {
System.out.println("SERVER Got EOFException");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
private void sendData(byte[] data, InetAddress ipAddress, int port) {
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, port);
try {
this.socket.send(packet);
}
catch (IOException e) {
e.printStackTrace();
}
}
private void sendObject(Object object) {
baos = new ByteArrayOutputStream(6400);
oos = null;
try {
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
}
catch (IOException e) {
e.printStackTrace();
}
sendData(baos.toByteArray(), packet.getAddress(), packet.getPort());
}
}
Client Side
public class GameClient extends Thread implements Serializable {
private InetAddress ipAddress;
private transient DatagramSocket socket;
private transient DatagramPacket packet;
private byte[] data;
private transient ByteArrayInputStream bais;
private transient ObjectInputStream ois;
private transient ByteArrayOutputStream baos;
private transient ObjectOutputStream oos;
private Game game;
public GameClient(String ipAddress) {
try {
this.socket = new DatagramSocket();
}
catch (SocketException e) {
e.printStackTrace();
}
try {
this.ipAddress = Inet4Address.getByName(ipAddress);
}
catch (UnknownHostException e) {
e.printStackTrace();
}
start();
}
#Override
public void run() {
while (true) {
data = new byte[6400];
packet = new DatagramPacket(data, data.length);
Object object = receive();
if (object instanceof String) {
System.out.println("SERVER >> " + object);
}
else if (object instanceof Game) {
this.game = (Game) object;
this.game.setClient(this);
this.game.start();
}
}
}
private Object receive() {
bais = new ByteArrayInputStream(data);
try {
socket.receive(packet);
ois = new ObjectInputStream(new BufferedInputStream(bais));
return ois.readObject();
}
catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
private void sendData(byte[] data) {
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, 1331);
try {
this.socket.send(packet);
}
catch (IOException e) {
e.printStackTrace();
}
}
public void sendObject(Object object) {
baos = new ByteArrayOutputStream(6400);
oos = null;
try {
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
}
catch (IOException e) {
e.printStackTrace();
}
sendData(baos.toByteArray());
}
}
Code to send the object to server
public class MultiplayerState extends State{
private World world;
private Tank myTank, playerTank;
public MultiplayerState(Handler handler) {
super(handler);
}
#Override
public void startState() {
world = new World(handler,"res/worlds/world1.txt");
handler.setWorld(world);
myTank = new Tank(handler, world.getSpawnX(), world.getSpawnY());
handler.getGame().getRender().addObject(world);
handler.getGame().getRender().addObject(myTank);
world.start();
myTank.start();
handler.getGame().getClient().sendObject(handler.getGame().getPlayer());
}
}
handler.getGame().getClient().sendObject(handler.getGame().getPlayer());
This line to send player to server .. some explanation about code .. this is a game using multithreading in java and i want to create simple network to make two different laptops playing this game online because of that i made this network. I created class Handler this is a class to manage all the game, using object instance of Handler class I can get anything in the game and I want to get object instance of Player class to send it to server because I want to do something to make the game online.
I solved this exception by made GameClient object in Game class transient because I don't want to serialize it. What I want is to use this object to send something to server from Game object internally.
I currently have a java program that requires quick communication between the client and server. I have decided to use UDP, after trying out TCP and RMI, which both were too slow for my purposes.
I have multiple ArrayLists that are stored in one ArrayList, which is then sent to the server. This method has worked fine in TCP and RMI, but it is required in UDP that this is changed to bytes.
ArrayList<Object> array = new ArrayList<Object>();
array.add(arrayList1);
array.add(arrayList2);
array.add(arrayList3);
array.add(arrayList4);
array.add(arrayList5);
array.add(arrayList6);
// Convert the ArrayList to bytes, then send to client
Each of the ArrayLists being added to the ArrayList that is being sent to the client contains objects and each ArrayList contains different types of objects. Most of the ArrayLists contain objects resulting from classes that I have created, but I do not think it is necessary to show them.
I have searched the internet for the answer to converting an ArrayList of ArrayLists to a byte, but the .getBytes() method does not work on the ArrayLists or the objects inside them.
If you need more examples of the code I am using, feel free to ask. The code above is not my real code(as numbering ArrayLists would be extremely confusing), but it is an accurate representation of what I am trying to achieve.
Thank you.
To do it in UDP, it would be something like this:
In view of server:
public static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(out);
os.writeObject(obj);
return out.toByteArray();
}
public static Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
ByteArrayInputStream in = new ByteArrayInputStream(data);
ObjectInputStream is = new ObjectInputStream(in);
return is.readObject();
}
public static void main(String[] args) {
new Server();
byte[] receiveData = new byte[65536];
byte[] sendData = new byte[65536];
try (DatagramSocket datagramSocket = new DatagramSocket(3333);) {
Board.start = true;
while (true) {
try {
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
datagramSocket.receive(receivePacket);
ArrayList<Object> object1 = (ArrayList)deserialize(receivePacket.getData());
InetAddress address = receivePacket.getAddress();
int port = receivePacket.getPort();
ArrayList<Object> array = new ArrayList<Object>();
array.add(arrayList1);
array.add(arrayList2);
array.add(arrayList3);
array.add(arrayList4);
array.add(arrayList5);
array.add(arrayList6);
sendData = serialize(array);
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, address, port);
datagramSocket.send(sendPacket);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
In view of client:
public static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(out);
os.writeObject(obj);
return out.toByteArray();
}
public static Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
ByteArrayInputStream in = new ByteArrayInputStream(data);
ObjectInputStream is = new ObjectInputStream(in);
return is.readObject();
}
public static void main(String[] args) {
new Client();
try {
DatagramSocket clientSocket = new DatagramSocket();
byte[] sendData = new byte[65536];
byte[] receiveData = new byte[65536];
while (true) {
try {
ArrayList<Object> fromUser = new ArrayList<Object>();
fromUser.add(arrayList1);
fromUser.add(arrayList2);
sendData = serialize(fromUser);
InetAddress address = InetAddress.getByName("localhost");
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, address, 3333);
clientSocket.send(sendPacket);
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
ArrayList<Object> object = (ArrayList)deserialize(receivePacket.getData());
arrayList1 = (ArrayList<Object>)object.get(0);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
I have found that this solution works for Java UDP using the serialization method,
public static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(out);
os.writeObject(obj);
return out.toByteArray();
}
public static Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
ByteArrayInputStream in = new ByteArrayInputStream(data);
ObjectInputStream is = new ObjectInputStream(in);
return is.readObject();
}
sending the ArrayList,
ArrayList<Object> array = new ArrayList<Object>();
array.add(arrayList1);
array.add(arrayList2);
array.add(arrayList3);
array.add(arrayList4);
sendData = serialize(array);
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, address, port);
datagramSocket.send(sendPacket);
and then receiving it.
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
ArrayList<Object> object = (ArrayList)deserialize(receivePacket.getData());
ArrayList<Object> arrayList = (ArrayList<Object>)object.get(0);
This seems to work for me, so I think that this method should work for you.
enter link description.
Here it this your solution.
To RMI I did it like that
In the view of Client
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.ArrayList;
import javax.swing.table.DefaultTableModel;
public interface InterfaceUsuario extends Remote {
public ArrayList< User >getList() throws RemoteException;
}
To get array data object:
In the view of Client
InterfaceUser or;
or = (InterfaceUser)Naming.lookup ("or");
ArrayList listUser = or.getList();
In the view of Server
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
private Session sesion;
private Transaction tx;
public class UserDAO {
public ArrayList<User> getListUser() throws Exception {
ArrayList<User> listContacts = null;
try
{
sesion = HibernateUtil.getSessionFactory().openSession();
tx = sesion.beginTransaction();
listContacts = (ArrayList<User>) sesion.createQuery("from User").list();
}finally
{
sesion.close();
}
return listContacts;
}
}
}
So I have seen a lot of different questions like this but no definitive help, at least to my understanding or my personal application. I am making a socket "chat room" program that allows the user to send images to selected users through a central server. I can establish the clients to connect but when sending an image this error occurs. Here is my code:
Client:
Thread thread = new Thread() {
#Override
public void run() {
try {
s = new Socket("localhost", 4000);
while (s.isConnected()) {
oos = new ObjectOutputStream(s.getOutputStream());
if (!initialized) {
oos.writeObject(identity);
oos.flush();
oos.reset();
initialized = true;
}
baos = new ByteArrayOutputStream(1000);
// Take screenshot
BufferedImage img = new Robot()
.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
// Write img to baos
ImageIO.write(img, "jpg", baos);
// Send image over socket
oos.writeObject(baos.toByteArray());
oos.flush();
oos.reset();
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
thread.start();
Central Server Home:
public Home() {
initComponents();
textView = new Terminal(terminal);
users = new CopyOnWriteArrayList<>();
Thread startServer = new Thread(new ServerStart());
startServer.start();
}
public class ServerStart implements Runnable {
#Override
public void run() {
try {
serverSock = new ServerSocket(4000);
terminal.append("Server started...\n");
while (true) {
// Detect client connection
Socket clientSock = serverSock.accept();
Thread thread = new Thread(new ClientHandler(clientSock));
thread.start();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public class ClientHandler implements Runnable {
Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
User user = new User(socket);
terminal.append(user.getName() + " connected as " + user.getType() + "...\n");
if (user.getType().equals(User.TYPE_01)) {
users.add(user);
} else {
User client = findUser(user);
while(true){
user.sendScreen(client.receiveScreen());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private User findUser(User user) {
for (User client : users) {
if (client.getCompany().equals(user.getCompany())) {
if (client.getName().equals(user.getName())) {
return client;
}
}
}
return null;
}
}
Central Server User:
public static final String TYPE_00 = "VIEWER";
public static final String TYPE_01 = "CLIENT";
private byte[] bytes;
private ObjectInputStream in;
private ObjectOutputStream out;
private String company, name, type;
public User(Socket socket) throws IOException {
this.out = new ObjectOutputStream(socket.getOutputStream());
this.in = new ObjectInputStream(socket.getInputStream());
setUserType();
}
public void sendScreen(byte[] bytes) {
try {
out.writeObject(bytes);
out.flush();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public byte[] receiveScreen() {
byte[] bytes = null;
try {
bytes = (byte[]) in.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return bytes;
}
public String getCompany() {
return company;
}
public String getName() {
return name;
}
public String getType() {
return type;
}
public void setUserType()
{
String[] strings = null;
try{
strings = (String[])in.readObject();
type = strings[0];
company = strings[1];
name = strings[2];
} catch(Exception e){
e.printStackTrace();
}
}
Client Viewer:
Thread thread = new Thread() {
#Override
public void run() {
try {
Socket s = new Socket("localhost",4000);
String[] strings = { TYPE, "Vision", "cadams" };
while (s.isConnected()) {
if(!initialized){
System.out.println("initialized");
oos = new ObjectOutputStream(s.getOutputStream());
oos.writeObject(strings);
oos.flush();
oos.reset();
initialized = true;
}
ois = new ObjectInputStream(s.getInputStream());
byte[] bytes = (byte[]) ois.readObject();
BufferedImage img = ImageIO.read(new ByteArrayInputStream(bytes));
ImageIcon ico = new ImageIcon(
img.getScaledInstance(viewer.getWidth(), viewer.getHeight(), Image.SCALE_SMOOTH));
viewer.setIcon(ico);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
thread.start();
}
I have done some extensive research and know that this could be from my streams looking like a bowl of ramen noodles but I haven't seen any sort of proposal on how to fix it in terms of source. I thank those who can contribute and please let me know if there is anything I can do to further understanding.
Don't keep creating new ObjectInput/OutputStreams. Use the same ones for the life of the socket.
NB while (s.isConnected() isn't valid. It doesn't magically become false when the peer disconnects. You need to handle end of stream and the various socket termination exceptions.