编写具有客户端服务器实用程序Windows功能的软件,第01部分

问候。

今天,我想分析编写执行标准Windows实用程序(例如Telnet,TFTP等)功能的客户端-服务器应用程序的过程,该过程使用纯Java语言编写。 显然,我不会带来任何新东西-所有这些实用程序已经成功运行了一年多,但是我相信并不是每个人都知道幕后发生的事情。

这将在裁员之下进行讨论。

在本文中,为了不耽误它,除了一般信息之外,我将只写有关Telnet服务器的信息,但是目前其他实用程序上仍然有资料-它将在本周期的后续部分中介绍。

首先,您应该了解什么是Telnet,为什么需要它以及被它吞噬了什么。 我不会一字不漏地引用源代码(如有必要,在文章末尾,我将附上相关资料的链接),我只能说Telnet提供了对设备命令行的远程访问。 总的来说,这就是功能结束的地方(我默默地无声地静静地联系了服务器端口,稍后再介绍)。 因此,对于其实现,我们需要在客户端上接受该行,将其传输到服务器,尝试将其传输到命令行,读取命令行响应(如果有),将其传输回客户端并显示,或者在发生情况下错误,使用户了解某些错误。

因此,要实现上述功能,您需要2个工作类,以及一些测试类,我们将从这些测试类中启动服务器并通过该类工作客户端。
因此,目前,该应用程序的结构包括:

  • Telnet客户端
  • TelnetClientTester
  • 远程登录服务器
  • Telnet服务器测试器

让我们逐一检查它们:

Telnet客户端

该课程仅能做的是发送收到的命令并显示收到的答案。 另外,您需要能够连接到远程设备的任意端口(如上所述)并断开连接。

为此,实现了以下功能:

一个以套接字地址作为参数,打开连接并启动输入和输出流的函数(流变量已在上面声明,完整的源代码在本文结尾)。

public void run(String ip, int port) { try { Socket socket = new Socket(ip, port); InputStream sin = socket.getInputStream(); OutputStream sout = socket.getOutputStream(); Scanner keyboard = new Scanner(System.in); reader = new Thread(()->read(keyboard, sout)); writer = new Thread(()->write(sin)); reader.start(); writer.start(); } catch (Exception e) { System.out.println(e.getMessage()); } } 

重载相同的功能,连接到默认端口-对于telnet,这是23

 public void run(String ip) { run(ip, 23); } 

该函数从键盘读取字符,并将其发送到输出套接字(通常以字符串而不是字符模式):

 private void read(Scanner keyboard, OutputStream sout) { try { String input = new String(); while (true) { input = keyboard.nextLine(); for (char i : (input + " \n").toCharArray()) sout.write(i); } } catch (Exception e) { System.out.println(e.getMessage()); } } 

该功能从套接字接收数据并将其显示在屏幕上。
 private void write(InputStream sin) { try { int tmp; while (true){ tmp = sin.read(); System.out.print((char)tmp); } } catch (Exception e) { System.out.println(e.getMessage()); } } 

该功能停止接收和发送数据。
 public void stop() { reader.stop(); writer.stop(); } } 

远程登录服务器

此类必须具有以下功能:从套接字接受命令,将其发送执行以将命令的响应发送回套接字。 该程序不会有意检查输入数据,因为首先,有机会在“盒式telnet”中格式化服务器磁盘,其次,原则上省略了本文中的安全性问题,这就是为什么没有关于加密或加密的问题。 SSL协议

只有两个函数(其中一个已重载),通常这不是一个好习惯,但是,作为此任务的一部分,在我看来,适当保留所有功能。

  boolean isRunning = true; public void run(int port) { (new Thread(()->{ try { ServerSocket ss = new ServerSocket(port); //          System.out.println("Port "+port+" is waiting for connections"); Socket socket = ss.accept(); System.out.println("Connected"); System.out.println(); //      ,       . InputStream sin = socket.getInputStream(); OutputStream sout = socket.getOutputStream(); Map<String, String> env = System.getenv(); String wayToTemp = env.get("TEMP") + "\\tmp.txt"; for (int i :("Connected\n\n\r".toCharArray())) sout.write(i); sout.flush(); String buffer = new String(); while (isRunning) { int intReader = 0; while ((char) intReader != '\n') { intReader = sin.read(); buffer += (char) intReader; } final String inputToSubThread = "cmd /c " + buffer.substring(0, buffer.length()-2) + " 2>&1"; new Thread(()-> { try { Process p = Runtime.getRuntime().exec(inputToSubThread); InputStream out = p.getInputStream(); Scanner fromProcess = new Scanner(out); try { while (fromProcess.hasNextLine()) { String temp = fromProcess.nextLine(); System.out.println(temp); for (char i : temp.toCharArray()) sout.write(i); sout.write('\n'); sout.write('\r'); } } catch (Exception e) { String output = "Something gets wrong... Err code: "+ e.getStackTrace(); System.out.println(output); for (char i : output.toCharArray()) sout.write(i); sout.write('\n'); sout.write('\r'); } p.getErrorStream().close(); p.getOutputStream().close(); p.getInputStream().close(); sout.flush(); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } }).start(); System.out.println(buffer); buffer = ""; } } catch(Exception x) { System.out.println(x.getMessage()); }})).start(); } 

该程序打开服务器端口,从中读取数据,直到遇到命令终止字符,将命令传输到新进程,并将该进程的输出重定向到套接字。 一切就像卡拉什尼科夫突击步枪一样。

因此,对于此功能,默认端口存在过载:

  public void run() { run(23); } 

好了,相应地,停止服务器的功能也很微不足道,它中断了永恒的周期,违反了它的条件。

  public void stop() { System.out.println("Server was stopped"); this.isRunning = false; } 

我不会在这里给出测试类,它们位于最底层-它们所做的只是检查公共方法的性能。 一切都在吉塔上。

总而言之,在几个晚上中,您可以了解主控制台实用程序的操作原理。 现在,当我们到达远程计算机时,我们了解发生了什么—魔力消失了)

因此,链接为:
所有消息来源都在,并将在这里
关于Telnet
有关Telnet的更多信息

Source: https://habr.com/ru/post/zh-CN460569/


All Articles