Проблема с использованием org.apache.commons.net.telnet. * С Android - PullRequest
12 голосов
/ 07 января 2010

У меня проблема с использованием библиотеки org.apache.commons.net.telnet.* в моем приложении для Android, и я надеялся, что кто-нибудь сможет мне помочь.

Я реализовал приложение, которое использует telnet для связи с удаленным сервером, и все работает нормально. У меня проблема, когда я вызываю TelnetClient.disconnect() метод не возвращается. При вызове метода при запуске тестового примера (то есть без Android, только через Eclipse) он сразу возвращается, но в Android что-то напортачило. Мой тестовый пример выглядел примерно так:

TelnetClient telnet = new TelnetClient();
telnet.connect(ipAddress, port); 
telnet.disconnect(); //HERE

Может ли кто-нибудь объяснить мне, почему это может быть?

Если я получаю InputStream от подключенного объекта telnet и некоторая информация отправляется с сервера telnet после вызова разрыва соединения, это может привести к возврату метода и закрытию потока связи, созданного путем вызова .connect(..) , что заставляет меня думать, что где-то хранится какая-то блокировка или замок?

Каким будет фундаментальное различие между виртуальной машиной Dalvik или ОС Android и моей машиной Java VM и XP, чтобы вызвать такое поведение?

Спасибо за любую помощь, следы стека ниже!

У меня есть трассировка стека из потока связи, созданного TelnetClient.connect() во время появления ANR (в результате бесконечного зависания вызова разъединения).

"Thread-15" daemon prio=6 tid=17 NATIVE | group="main" sCount=1 dsCount=0 s=N                obj=0x43812d90 self=0x1be528 | sysTid=1403 nice=-2 sched=0/0 handle=2703408 
  at org.apache.harmony.luni.platform.OSNetworkSystem.receiveStreamImpl(Native Method) 
  at org.apache.harmony.luni.platform.OSNetworkSystem.receiveStream(OSNetworkSystem.java:236) 
  at org.apache.harmony.luni.net.PlainSocketImpl.read(PlainSocketImpl.java:550) 
  at org.apache.harmony.luni.net.SocketInputStream.read(SocketInputStream.java:87) 
  at org.apache.harmony.luni.net.SocketInputStream.read(SocketInputStream.java:67) 
  at java.io.BufferedInputStream.fillbuf(BufferedInputStream.java:177) 
  at java.io.BufferedInputStream.read(BufferedInputStream.java:259) 
  at java.io.PushbackInputStream.read(PushbackInputStream.java:160) 
  at org.apache.commons.net.io.FromNetASCIIInputStream._read(FromNetASCIIInputStream.java:77) 
  at org.apache.commons.net.io.FromNetASCIIInputStream.read(FromNetASCIIInputStream.java:175) 
  at org.apache.commons.net.io.FromNetASCIIInputStream.read(FromNetASCIIInputStream.java:138) 
  at java.io.BufferedInputStream.fillbuf(BufferedInputStream.java:177) 
  at java.io.BufferedInputStream.read(BufferedInputStream.java:259) 
  at org.apache.commons.net.telnet.TelnetInputStream._read(TelnetInputStream.java:122) 
  at org.apache.commons.net.telnet.TelnetInputStream.run(TelnetInputStream.java:564) 
  at java.lang.Thread.run(Thread.java:1060)

А также из потока, вызывающего .disconnect() (который для моего тестового примера находится только в основном потоке):

DALVIK THREADS: "main" prio=5 tid=3 MONITOR | group="main" sCount=1 dsCount=0 s=N   obj=0x4001ab08 self=0xbc60 | sysTid=1390 nice=0 sched=0/0 handle=-1343996920 
  at java.io.BufferedInputStream.close(BufferedInputStream.java:~166) 
  at org.apache.commons.net.telnet.TelnetInputStream.close(TelnetInputStream.java:535) 
  at java.io.FilterInputStream.close(FilterInputStream.java:81) 
  at java.io.BufferedInputStream.close(BufferedInputStream.java:167) 
  at couk.mypackage.comm.TelnetClient.closeTelnet(IGSTelnetClient.java:441) 
  at couk.myoackage.comm.Translator$1.handleMessage(IGSTranslator.java:65) 
  at android.os.Handler.dispatchMessage(Handler.java:99) 
  at android.os.Looper.loop(Looper.java:123) 
  at android.app.ActivityThread.main(ActivityThread.java:4203) 
  at java.lang.reflect.Method.invokeNative(Native Method) 
  at java.lang.reflect.Method.invoke(Method.java:521) 
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791) 
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549) 
  at dalvik.system.NativeStart.main(Native Method)

Обновление:

Если я закрою выходной и входной потоки явно (что javadoc говорит НЕ делать), но вместо этого вызову disconnect(), тогда я могу закрыть соединение, т.е.

out.close();
in.close();
telnet.disconnect();

Я в замешательстве!

1 Ответ

1 голос
/ 19 августа 2011

TelentClient extends Telnet и Telnet extends SocketClient. Если вы видите эти классы, это создаст VT100 соединение. См. Код ниже TelnetClient.java.

 public TelnetClient() {
   /* TERMINAL-TYPE option (start)*/
   super ("VT100");
   /* TERMINAL-TYPE option (end)*/
   __input = null;
   __output = null;
 }

Теперь будут созданы суперклассы. Смотрите код от Telnet.java класс.

Telnet() {
      setDefaultPort(DEFAULT_PORT);
      _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
      _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
      _options = new int[TelnetOption.MAX_OPTION_VALUE + 1];
      optionHandlers = new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1];
}

DEFAULT_PORT здесь 23.

Теперь посмотрите метод connect из SocketClient.java.

        public void connect(InetAddress host, int port)
                throws SocketException, IOException {
            _socket_ = _socketFactory_.createSocket(host, port);
            _connectAction_();
        }

Это создает новый Socket с использованием DefaultSocketFactory, который является TCP-сокетом для указанного хоста и порта. В методе connectAction устанавливается время ожидания для нового сокета.

Теперь, когда мы вызываем disconnect, сначала пытается закрыть сокет.

public void disconnect() throws IOException {
            _socket_.close();
            _input_.close();
            _output_.close();
            _socket_ = null;
            _input_ = null;
            _output_ = null;
            _isConnected_ = false;
        }

Поскольку вы можете закрывать потоки напрямую, возникает проблема с самим сокетом.

Это будет сокет TCP, и я не знаю, как Android ведет себя с TCP. Можете ли вы проверить это? Потому что этот метод делает закрытие 3 закрытых членов. ИЛИ, может быть, сокет уже закрыт, так что он не может закрыть его снова?

Надеюсь, это поможет.

Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...