новые блоки ObjectInputStream()

public class SerProg {


    static ServerSocket ser=null;
    static Socket cli=null;
    static ObjectInputStream ins=null;
    static ObjectOutputStream outs=null;


    public static void main(String[] args) {

        try {

            ser=new ServerSocket(9000,10);
            cli=ser.accept();

            System.out.println("Connected to :"+cli.getInetAddress().getHostAddress()+" At Port :"+cli.getLocalPort());

            ins=new ObjectInputStream(cli.getInputStream());
            outs=new ObjectOutputStream(cli.getOutputStream());

            String str=(String)ins.readObject();


        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

}

И клиент

public class SerProg {

    /**
     * @param args
     */
    static ServerSocket ser=null;
    static Socket cli=null;
    static ObjectInputStream ins=null;
    static ObjectOutputStream outs=null;


    public static void main(String[] args) {
        // TODO Auto-generated method stub

        try {

            ser=new ServerSocket(9000,10);
            cli=ser.accept();

            System.out.println("Connected to :"+cli.getInetAddress().getHostAddress()+" At Port :"+cli.getLocalPort());

            ins=new ObjectInputStream(cli.getInputStream());
            outs=new ObjectOutputStream(cli.getOutputStream());

            String str=(String)ins.readObject();


        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

}

Соединение установлено успешно, но в строке кода сервера

ins=new ObjectInputStream(cli.getInputStream());

код зависает и не запускается, в чем может быть проблема??


person Abhishek    schedule 01.01.2013    source источник
comment
Вы дважды прошли код SerProg   -  person benjarobin    schedule 01.01.2013


Ответы (2)


Вам нужно создать ObjectOutputStream перед ObjectInputStream с обеих сторон соединения (!). Когда создается ObjectInputStream, он пытается прочитать заголовок потока объектов из файла InputStream. Поэтому, если ObjectOutputStream на другой стороне еще не создано, нет заголовка потока объектов для чтения, и он будет заблокирован на неопределенный срок.

Или сформулировать по-другому: если обе стороны сначала создают ObjectInputStream, обе заблокируют попытку чтения заголовка потока объектов, который не будет записан до тех пор, пока не будет создан ObjectOutputStream (на другой стороне строки); чего никогда не произойдет, потому что обе стороны заблокированы в конструкторе ObjectInputStream.

Это можно сделать из документа Javadoc ObjectInputStream(InputStream in):

Заголовок потока сериализации считывается из потока и проверяется. Этот конструктор будет блокироваться до тех пор, пока соответствующий ObjectOutputStream не запишет и не сбросит заголовок.

Это также описано в разделе 3.6.2 книги Fundamental networking in Java Эсмонда Питта.

person Mark Rotteveel    schedule 01.01.2013
comment
Я не понимаю, почему порядок актуален между ObjectOutputStream и ObjectInputStream - person benjarobin; 01.01.2013
comment
@benjarobin Если обе стороны сначала создадут ObjectInputStream, обе заблокируют попытку чтения заголовка потока объектов, который не будет записан до тех пор, пока не будет создан ObjectOutputStream (на другой стороне строки); чего никогда не произойдет, потому что обе стороны заблокированы в конструкторе ObjectInputStream. - person Mark Rotteveel; 01.01.2013
comment
Извините, я неправильно понял ваше сообщение, извините !!! Ваш комментарий очень ясен, вы должны добавить его в свой ответ. Я не понял, что и клиент, и сервер отправляют объект в обоих направлениях (мой плохой) Вы получаете +1 от меня :-) - person benjarobin; 01.01.2013
comment
Я видел много повторяющихся вопросов на этот, у всех один и тот же ответ, к сожалению, это решение мне не подходит, есть ли у вас какие-либо другие предложения для меня? - person BHA Bilel; 04.04.2021
comment
@danibilel В некоторых реализациях может потребоваться явный вызов flush() для ObjectOutputStream сразу после создания, перед созданием ObjectInputStream. Однако во всех случаях вы должны построить выход перед входом с обеих сторон, чтобы предотвратить взаимное ожидание. - person Mark Rotteveel; 04.04.2021
comment
Спасибо за ваш ответ, мой случай был более сложным, чем установка соединения клиент/сервер, я исправил его, повторно создав экземпляр serversocket. - person BHA Bilel; 04.04.2021

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

//SERVER SIDE
Socket clientSocket = TcpServer.socket.accept();
// 1. input stream;
ObjectInputStream sInput = new ObjectInputStream(clientSocket.getInputStream());
// 2. output stream
ObjectOutputStream sOutput = new ObjectOutputStream(clientSocket.getOutputStream());


//CLIENT SIDE
Socket socket = new Socket(ip, port);
// 2. output stream
ObjectOutputStream sOutput = new (socket.getOutputStream());
// 1. input stream
ObjectInputStream sInput = new ObjectInputStream(socket.getInputStream());

Я попытался показать, как сделать рукопожатие для потоков.

person samet kaya    schedule 23.02.2020
comment
ObjectOutputStream не обязательно должна быть клиентская сторона, которая создает ObjectOutputStream первой: это может быть любая сторона, но безопаснее сначала создать ее на обаих концах. Тогда у вас не может быть проблем. - person user207421; 14.11.2020