2012-03-22 37 views
0

我无法从我的“Telnet”接口的C/C++过渡到Java到我们在这里使用的一些模块。我希望能够与卡建立连接,在启动它的命令行界面后,等待连接并向客户端提供提示(“OK>”)。这对我编写的C和C#客户端来说都很好,但Java给了我一些问题。我附加了一些代码,我从一些在线示例中获得了代码,但到目前为止,我可以确定的是,套接字正在创建。在Java“Telnet”代码中使用套接字流问题?

代码:

private boolean CreateTelnetSession() 
    { 
     try 
     { 
      _socket = new Socket(); 
      _socket.connect(new InetSocketAddress(_ipAddr, _ipPort)); 
      _socket.setSoTimeout(10000); 
      _socket.setKeepAlive(true); 

      _out = new PrintWriter(_socket.getOutputStream(), true); 
      _in = new BufferedReader(new InputStreamReader(_socket.getInputStream())); 

      _out.println("\r\n"); 

      System.out.println(_in.readLine()); 

      return true; 
     } 
     catch(Exception e) 
     { 
      System.out.println("Exception!"); 
     } 
     return false; 
    } 

插座似乎是正确创建,当程序关闭,我可以看到接近卡(S)我想谈的会议,但我没有看到卡片上的回车/换行符,因为我期望,或通过InputStream返回提示。这可能是一个字符编码问题吗?我正在做什么不正确的流(穿过他们!?!)?任何洞察力呢?当我在这个最初的学习曲线,我想肯定容易的Java如何使这些插座的读取和写入,但在那之前......

我看到这篇文章: java simple telnet client using sockets

似乎类似于我遇到了,但它不一样。如果有人在这里看到某件事解决了我的问题,我愿意承担这个责任,所以请直接告诉我,我错过了什么。

编辑:

private boolean CreateTelnetSession() 
{ 
    try 
    { 
     _socket = new Socket(); 
     _socket.connect(new InetSocketAddress(_ipAddr, _ipPort)); 
     _socket.setSoTimeout(10000); 
     _socket.setKeepAlive(true); 

     _out = new DataOutputStream(_socket.getOutputStream()); 
     _in = new DataInputStream(_socket.getInputStream()); 

     _outBuffer = ByteBuffer.allocate(2048); 
     _outBuffer.order(ByteOrder.LITTLE_ENDIAN); 
     _inBuffer = ByteBuffer.allocate(2048); 
     _inBuffer.order(ByteOrder.LITTLE_ENDIAN); 

     System.out.println("Connection Response: " + _in.read(_inBuffer.array())); 
     System.out.println("Response: " + WriteCommand("DRS\r\n")); 

     return true; 
    } 
    catch(Exception e) 
    { 
     System.out.println("Exception!"); 
    } 
    return false; 
} 

private String WriteCommand(String command) 
{ 
    try 
    { 
     _outBuffer = encoder.encode(CharBuffer.wrap(command)); 
     _out.write(_outBuffer.array()); 
     _out.flush(); 

     _in.read(_inBuffer.array()); 
     String retString = decoder.decode(_inBuffer).toString(); 

     return retString.substring(0, retString.indexOf('>') + 1); 
    } 
    catch(Exception e) 
    { 
     System.out.println("Exception!"); 
    } 

    return "E1>"; 
} 

有很多东西要收拾,我要与我是否需要做的是在相当这样的实验,但这是“解决方案的要点”。最大的杀手是排序。应该再次提到,这是丑陋的,非生产性的代码,但任何其他意见仍然值得赞赏。

回答

1

我有几件事情可以尝试。您正在使用PrintWriter作为您的输出,这是一个相当高级的Writer(即它封装了很多来自您的内容)。我担心的是PrintWriter中的println()方法会在最后自动添加一个行结束符(适用于您的操作系统)。所以你真正发送的是“/ r/n(行结束符)”,所以在你将发送“/ r/n/n”的unix盒子上。

我建议切换到DataOutputStream类,让你在所有发送的原始字节更多的控制:http://docs.oracle.com/javase/6/docs/api/java/io/DataOutputStream.html

记住,如果你切换到DataOutputStream类需要调用flush的输出流。

我的另一个想法是它可能是一个endianess问题。 Java严格地说是Big Endian(网络字节顺序)。是否有可能你的“卡”正在阅读小尾巴的东西?如果你需要通过网络进行小端编码(如果你的网卡是一个不好的网友!),你将需要使用一个ByteBuffer,将它的顺序设置为小端。将字节写入它,然后将字节从ByteBuffer写入DataOutputStream。

我也可能会切换到您的输入流的DataInputStream。只有在看到换行符后,readline()才会返回。你的卡在回复中是否返回换行符?

我最后的想法是,你的println方法可能有错误,你不知道它,因为PrintWriter不会抛出异常。PrintWriter JavaDocs说:

“这个类中的方法不会抛出I/O异常,虽然它的一些构造函数可能会通过调用checkError()来查询是否发生了任何错误。

希望我漫长的回应能帮助你。

+0

你用endian-ness钉了它。该卡/模块驻留在处理所有“网民”内容的机箱中。我正在(重新)编写的软件是用于控制机箱中n个这样的模块,所以我认为我可以放心地认为它不必与其他网络设备打好关系。谢谢你的帮助! – 2012-03-22 18:20:52

+1

很高兴能帮到你! Endian-ness不是我想到的第一件事,但是一旦我想到它,我认为它是最可能的问题。 – Michael 2012-03-22 18:41:19