我在我的 Android 应用程序中使用 org.apache.commons.net.telnet.*
库时遇到问题,我希望有人能帮助我。
我已经实现了一个使用 telnet 与远程服务器通信的应用程序,并且一切正常。我遇到的问题是,当我调用 TelnetClient.disconnect()
时,该方法没有返回。当在运行测试用例时调用该方法(意味着没有 Android,仅通过 Eclipse)它立即返回,但在 Android 上有些东西搞砸了。我的测试用例看起来像:
TelnetClient telnet = new TelnetClient();
telnet.connect(ipAddress, port);
telnet.disconnect(); //HERE
谁能告诉我为什么会这样?
如果我从已连接的 telnet 对象获得一个 InputStream
并且在调用断开连接后从 telnet 服务器发送了一些信息,它可能导致该方法返回并关闭创建的 comm 线程通过调用 .connect(..)
,这让我觉得某处有某种类型或锁定?
Dalvik VM 或 Android OS 与我的 Java VM 和 XP 机器之间的根本区别是什么导致该行为?
感谢您的帮助,堆栈跟踪如下!
在出现 ANR 时(由于断开连接调用无限期挂起),我有来自 TelnetClient.connect()
创建的通信线程的堆栈跟踪。
"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();
我很困惑!
最佳答案
TelentClient 扩展了 Telnet
和 Telnet 扩展了 SocketClient
。如果您看到这些类,它将创建 VT100
连接。请参阅 TelnetClient.java
中的以下代码。
public TelnetClient() {
/* TERMINAL-TYPE option (start)*/
super ("VT100");
/* TERMINAL-TYPE option (end)*/
__input = null;
__output = null;
}
这将创建父类(super class)。请参阅 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
。
现在,查看 SocketClient.java
中的 connect
方法。
public void connect(InetAddress host, int port)
throws SocketException, IOException {
_socket_ = _socketFactory_.createSocket(host, port);
_connectAction_();
}
这是使用 DefaultSocketFactory
创建一个新的 Socket
,这是一个到指定主机和端口的 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 个私有(private)成员。或者可能套接字已经关闭,因此无法再次关闭?
希望这对您有所帮助。
谢谢。
关于java - 在 android 中使用 org.apache.commons.net.telnet.* 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2019539/