Search code examples
javasocketssynchronizationthreadpoolobjectoutputstream

ObjectOutputStream stops working without error message


I am currently working on a video transmission program involving a client sender, a server receiver, and multiple client receivers. The sender sends video frames every 75ms to the server, which then broadcasts these frames to a group of client receivers.

The issue I am encountering is that after approximately 4 or 5 iterations, the server stops broadcasting frames to the clients, even though it continues to receive frames from the sender without any errors. Any help or suggestion would be much appreciated.

This is the sender code:

public void sendImageToServer(BufferedImage screenshot) {
    try {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageIO.write(screenshot, "jpeg", byteArrayOutputStream);           
        byte[] imageBytes = byteArrayOutputStream.toByteArray();

        objectOutputVideoStream.writeObject(imageBytes);
        objectOutputVideoStream.flush();
        System.out.println("Frame sent");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

This is the server code:

private ExecutorService pool = Executors.newCachedThreadPool();

    public void receiveAndBroadcastVideo(Socket socket, int roomId) {
        try {
            InputStream inputStream = socket.getInputStream();
            ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
            while (true) {
                byte[] imageBytes = (byte[]) objectInputStream.readObject();
                System.out.println("Frame ricevuto");
                List<UserWithSocket> roomClients = videoChatRoomClients.get(roomId);
                for (UserWithSocket client : roomClients) {
                    if(client.getUserSocket()!=socket) {
                        pool.submit(() -> {
                            try {
                                ObjectOutputStream clientObjectOutputStream = client.getClientObjectOutputStream();
                                synchronized (clientObjectOutputStream) {
                                    clientObjectOutputStream.write(imageBytes);
                                    clientObjectOutputStream.flush();
                                }
                                System.out.println("Frame Broadcasted");
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        });
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

And this is where I create the ObjectOutputStream:

public class UserWithSocket {

    private int id;
    private Socket userSocket;
    private ObjectOutputStream clientObjectOutputStream;

    public UserWithSocket(int id, Socket userSocket) {
        super();
        this.id = id;
        this.userSocket = userSocket;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Socket getUserSocket() {
        return userSocket;
    }

    public void setUserSocket(Socket userSocket) {
        this.userSocket = userSocket;
    }

    public void createStream() {
        try {
            OutputStream outputStream = userSocket.getOutputStream();
            clientObjectOutputStream = new ObjectOutputStream(outputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public ObjectOutputStream getClientObjectOutputStream() {
        return clientObjectOutputStream;
    }

    public void setClientObjectOutputStream(ObjectOutputStream clientObjectOutputStream) {
        this.clientObjectOutputStream = clientObjectOutputStream;
    }
    
    
}

Since I'm not receiving any kind of error it might be a deadlock situation, I just know that after 4 or 5 iterations this part of the code won't run:

synchronized (clientObjectOutputStream) {
    clientObjectOutputStream.write(imageBytes);
    clientObjectOutputStream.flush();
}

Solution

  • I wrote clientObjectOutputStream.write(imageBytes); instead of clientObjectOutputStream.writeObject(imageBytes);

    after using writeObject it worked perfectly fine.