Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Работа с сетью > Клиент виснет при ожидании данных


Автор: Norb 28.2.2008, 22:59
Передо мной стоит задача - написать сервер и клиент подобия ICQ,  но для локальной сети. Функциональность конечно точно такая же не требуется, главное - передача сообщений. Для этого создал класс Message и кидаюсь его объектами через ObjectInputStream и ObjectOutputStream. В общем всё нормально, сообщения приходят (пока хотя бы на сервер). Правда в начале столкнулся с той же проблемой, что и господин sith в теме http://forum.vingrad.ru/topic-143781.html. Причём тоже не мог её решить, в том числе и тем способом, который был указан там. Объяснить каким именно образом проблема разрешилась сам точно не могу, но ситуация изменилась когда объект класса ObjectOutputStream стал объявлять до объекта ObjectInputStream. Теперь же суть проблемы вот в чём - клиент должен постоянно находиться в состоянии ожидания входящих сообщений, то есть должен быть цикл, что-то вроде этого:
Код

                Socket s = new Socket(cw.ip.getText(), 3512);

                ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream());
                ObjectInputStream in = new ObjectInputStream(s.getInputStream());

                Message m = new Message(0);

...

                while (s.isConnected()) {
                    try {
                        m = (Message) in.readObject();
                           // обработка входящих сообщений
                    }
                    catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }

Но как раз в этом месте программа виснет и не подаёт признаков жизни. Что делать не знаю, ведь на сервере реализация ожидания сообщений аналогичная и работает превосходно. Причём сервер не виснет и если объект ObjectInputStream объявлять раньше ObjectOutputStream
Код

           ServerSocket s = new ServerSocket(port);
           Socket incoming = s.accept();

            ObjectInputStream in = new ObjectInputStream(incoming.getInputStream());
            ObjectOutputStream out = new ObjectOutputStream(incoming.getOutputStream());

.......

            while (incoming.isConnected()) {
                try {
                    Message mess = (Message) in.readObject();
                    // обработка входящих сообщений
                }
                catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }

Подскажите, пожалуйста, что делать, заранее спасибо!

Автор: COVD 28.2.2008, 23:25
чего-то у вас в коде все читают, а никто не пишет. А вообще, использование RMI в вашей задаче было бы уместно.

Автор: sith 29.2.2008, 14:59
Norb, ох прикольно конгда темы годичной давности возвращаються smile  
... потеме скажу следующее... этот проектик я так и не закончил так как в дальнейшем запутался с потоками... сейчас все обдумав с высоты уже приобретенного опыта скажу что RMI это точто здесь нужно... ведь фактически то что делаешь ты и я это тоже самое, только самописное... а это технология уже существует и живет... так что  я думаю в данном случае велосипед нет смысла изобретать... смотри в стороно RMI

Автор: niasilil 5.3.2008, 21:14
Цитата(Norb @ 28.2.2008,  22:59)
Но как раз в этом месте программа виснет и не подаёт признаков жизни. Что делать не знаю, ведь на сервере реализация ожидания сообщений аналогичная и работает превосходно. 

поставить сокет таймаут на 100 миллисекунд. Программа будет в режиме ожидания это время, потом будет проверять очередь сообщений - есть ли что то чтобы послать. Примерно так
Код

public class Connector extends Thread {

    private Socket socket;
    private InputStreamReader isr;
    private BufferedReader br;
    private OutputStreamWriter osw;
    private PrintWriter pw;
    private ArrayList<String> out = new ArrayList<String>();
    private boolean stop = false;
    private final int TIMEOUT = 200;

    /** Logger. */
    private Logger logger = Logger.getLogger("Connector");
    private boolean toSend;

    public Connector(Socket socket) {
        this.socket = socket;

        try {
            this.socket.setSoTimeout(TIMEOUT);

            isr = new InputStreamReader(socket.getInputStream());
            br = new BufferedReader(isr);

            osw = new OutputStreamWriter(socket.getOutputStream());
            pw = new PrintWriter(osw, true);

            logger.info("Socket streams initialized");
        } catch (IOException e) {
            logger.warning("Socket failed " + e.getMessage());
        }
    }

    @Override
    public void run() {
        try {
            while (!stop) {
                try {
                    String result;

                    result = br.readLine();
                    logger.info("Received message " + ": " + result);

                    if (result != null || !result.trim().isEmpty()) {
                        // do something;
                    }
                } catch (SocketTimeoutException e) {
                    // do nothing
                }

                if (toSend) {
                    send();
                }
            }
        } catch (IOException e) {
            JOptionPane.showMessageDialog(null, "Network failed", "Network failed",
                    JOptionPane.WARNING_MESSAGE);
            logger.severe("Socket failed " + e.getMessage());
        }
    }

    /**
     * Sends the data
     */
    private void send() {
        synchronized (out) {
            for (String s : out) {
                pw.println(s);
                pw.flush();
                logger.info("Message is sent: [" + s + "]");
            }
            out.clear();
            // set flag for sending
            toSend = false;
        }
    }

    public void addMessageOut(String msg) {
        synchronized (out) {
            out.add(msg);
        }
        toSend = true;
        logger.info("outgoing message added: " + msg);
    }
}

ну или асинхронный клиент с разными threads для send и receive

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)