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


Автор: AleksPingvin 20.5.2012, 11:16
Понадобилось в клиенте реализовать возможность отправки синхронных команд.

Есть базовый класс с объявленным ReetrantLock-ом и созданным на его базе Condition-ом.
Первое, что пришло в голову - после захвата блокировки и отправки пакета на сервер делать await(TIMEOUT) у condition, а в методе IoHandler.messageRecive делать для кондишена signalAll().
Предварительно я выставил:
Код

connector.getFilterChain().addLast( "Executor", new ExecutorFilter());

Сам код отправки выглядел примерно так:
Код

lock.lock();
try{
handler.setWaitCmdIdAswer(cmd.getCmdId());
            executeCmd(cmd); //Исполняется команда и в сессию пишется результат
            
            if (handler.getAnswerSyncCmd() == null && isConnected())
                answerMonitor.await(30, TimeUnit.SECONDS);
           
            //Пришел ответ на синхронную команду либо истек таймаут
            Container result = handler.getAnswerSyncCmd();
            handler.acceptAnswerSyncCmd();*/
            
        } catch (Exception e) {
            log.error("", e);
            return null;
        } finally {
            lock.unlock();
        }

Код приема:
Код

 public void messageReceived(IoSession session, Object message) throws Exception {
        ......
        Container cont = (Container)message;
       
        if (waitCmdIdAswer != null && waitCmdIdAswer.equals(cont.getCmdId())){
         
            answerSyncCmd = cont;
            conn.getLock().lock();
            try{
                conn.getAnswerMonitor().signalAll();
            }finally{
                conn.getLock().unlock();
            }
        }else{
            //Пришел ответ на асинхронную команду или просто команда от сервера
            conn.notifyListenerCmdAnswer(cont);
        }
        
           
    }

В результате получил следующий эффект - сервер получает команду, отрабатывает и возвращает результат. Декодер на клиенте регистрирует получение сообщения, отрабатывает его, возвращает true и... все. Пока не истечет таймаут сообщение в  IoHandler не поступает.

Побившись пару часов и не придя к решению, попробовал сделать по феншую:
Код

final WriteFuture writeFuture  = session.write(data);
            writeFuture.awaitUninterruptibly();
        

            if (writeFuture.getException() != null) {
                session.getConfig().setUseReadOperation(false);
                return null;
            }

            // retrieve the login response
            final ReadFuture readFuture =session.read();
            readFuture.awaitUninterruptibly();

            if (readFuture.getException() != null) {
                session.getConfig().setUseReadOperation(false);
                return null;
            }

            // stop blocking inbound messages
            session.getConfig().setUseReadOperation(false);

            // determine if the login info provided was valid
            final Container reusult = (Container)readFuture.getMessage();

Однако проблема осталась точно такая же, после обработки декодером сообщение не поступает ни куда. В данном коде мы просто "повиснем" на  readFuture.awaitUninterruptibly();

Подскажите - как быть?

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