DataOutputStream застревает

Я сделал простое серверное приложение для отправки изображений на подключенные клиенты. У меня есть цикл в главном потоке, который принимает входящие соединения и делает объект клиента из соответствующего сокета. У меня есть список для активных клиентов. Каждый раз, когда появляется новая картинка, я перебираю клиентов и отправляю им новые данные. Если все остаются на связи, все идет хорошо. Но как только один из клиентов отключается, метод записи DataOutputStream застревает навсегда. Я предполагал, что это должно вызвать исключение или что-то, но это не так. Я думаю, что скучаю по чему-то простому, но не могу понять, что. Вот код моего класса клиента:

package hu.rothens.webcam;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class Client {

    private static int next_id = 0;
    private int id;
    private Socket socket;
    private WebcamServer ws;
    private DataOutputStream dos;

    public Client(Socket socket, WebcamServer ws, int width, int height) throws IOException {
        this.socket = socket;
        this.ws = ws;
        id = next_id++;
        while (!socket.isConnected());
        dos = new DataOutputStream(socket.getOutputStream());
        dos.writeInt(width);
        dos.writeInt(height);
    }

    public synchronized void sendImage(byte[] array) {
        try {
            System.out.println(id);
            //the code will stuck somewhere after this line
            dos.writeByte(0xFF);
            dos.flush();
            dos.writeInt(array.length);
            dos.write(array);
            dos.flush();
        } catch (IOException e) {
            System.out.println(e); //it won't get here
            ws.removeClient(this);
            try {
                socket.close();
            } catch (Exception ex) {
            }
        }    
    }
}

1 ответ

Это не блокирует навсегда. Это вызовет IOException: "сброс соединения" в конце концов. "Навсегда" подразумевает тупик с вашей стороны.

'While (! Socket.isConnected());' Цикл совершенно бессмысленный: сокет подключен, благодаря тому, что был принят. И если это не так, это не способ справиться с этим.

Вы не должны очищать поток после записи 0xff, но вы должны очищать его в конструкторе для клиента.

Я не вижу никакой причины для синхронизации в клиенте, если он работает в своем собственном потоке, что и должно быть.

Вы должны отправлять всем клиентам одновременно, а не итеративно, чтобы все они обслуживались одновременно, и чтобы ошибки или медлительность в одном не влияли на других.

Другие вопросы по тегам