Schreiwen Software mat der Funktionalitéit vu Windows Client-Server Utilities, Deel 01

Gréiss.

Haut wëll ech de Prozess kucken fir Client-Server Uwendungen ze schreiwen, déi d'Funktioune vu Standard Windows Utilities ausféieren, wéi Telnet, TFTP, etc., etc a pure Java. Et ass kloer datt ech näischt Neies bréngen - all dës Utilitys hunn méi wéi ee Joer erfollegräich geschafft, awer ech gleewen datt net jidderee weess wat ënner der Hood lass ass.

Genee dat wäert ënnert dem Schnëtt diskutéiert ginn.

An dësem Artikel, fir et net ze zéien, nieft allgemeng Informatioun, wäert ech nëmmen iwwer den Telnet Server schreiwen, awer de Moment gëtt et och Material iwwer aner Utilities - et wäert an weideren Deeler vun der Serie sinn.

Als éischt musst Dir erausfannen wat Telnet ass, fir wat et ass a fir wat et benotzt gëtt. Ech zitéieren keng Quelle wuertwiertlech (wann néideg, befestegt ech e Link op d'Materialien zum Thema um Enn vum Artikel), ech soen nëmmen datt Telnet Remote Zougang zu der Kommandozeil vum Apparat ubitt. Am grousse Ganzen ass dat wou seng Funktionalitéit endet (ech hunn bewosst roueg gehalen iwwer den Zougang zum Serverport; méi doriwwer méi spéit). Dëst bedeit datt fir et ëmzesetzen, musse mir eng Zeil um Client akzeptéieren, se un de Server passéieren, probéieren se op d'Kommandolinn ze passéieren, d'Kommandolinn Äntwert liesen, wann iwwerhaapt, se zréck un de Client weiderginn an se weisen um Écran, oder, wann Feeler, Loosst de Benotzer wëssen, datt eppes falsch ass.

Fir déi uewe genannten ëmzesetzen, brauche mir deementspriechend 2 Aarbechtsklassen an e puer Testklass, aus deem mir de Server starten an duerch deen de Client funktionnéiert.
Deementspriechend enthält de Moment d'Applikatiounsstruktur:

  • TelnetClient
  • TelnetClientTester
  • TelnetServer
  • TelnetServerTester

Loosst eis all vun hinnen duerchgoën:

TelnetClient

All dës Klass soll fäeg sinn ze maachen ass kritt Kommandoen ze schécken an déi kritt Äntwerten ze weisen. Zousätzlech musst Dir fäeg sinn mat engem arbiträren (wéi uewen ernimmt) Hafen vun engem Fernapparat ze verbannen an dovunner ofzekoppelen.

Fir dëst z'erreechen, goufen déi folgend Funktiounen ëmgesat:

Eng Funktioun déi eng Socket-Adress als Argument hëlt, eng Verbindung opmaacht an d'Input- an d'Outputstroum start (Streamvariablen ginn uewen deklaréiert, voll Quelle sinn um Enn vum Artikel).

 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());
        }
    }

Iwwerlaascht déiselwecht Funktioun, verbënnt mam Standardport - fir Telnet ass dëst 23


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

D'Funktioun liest Zeechen vun der Tastatur a schéckt se an d'Ausgangssocket - wat typesch ass, am Zeilmodus, net Charaktermodus:


    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());
        }
    }

D'Funktioun kritt Daten aus der Socket a weist se um Bildschierm


    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());
        }
    }

D'Funktioun stoppt Datenempfang an Iwwerdroung


    public void stop()
    {
        reader.stop();
        writer.stop();
    }
}

TelnetServer

Dës Klass muss d'Funktionalitéit hunn fir e Kommando aus engem Socket ze kréien, et fir Ausféierung ze schécken an eng Äntwert vum Kommando zréck an de Socket ze schécken. De Programm kontrolléiert bewosst d'Inputdaten net, well éischtens, och am "Boxed Telnet" ass et méiglech de Serverdisk ze formatéieren, an zweetens ass d'Fro vun der Sécherheet an dësem Artikel am Prinzip ausgelooss, an dofir ass et net e Wuert iwwer Verschlësselung oder SSL.

Et ginn nëmmen 2 Funktiounen (eng vun hinnen ass iwwerlaascht), an allgemeng ass dëst net eng ganz gutt Praxis, awer fir d'Ziler vun dëser Aufgab war et mir passend alles ze loossen wéi et ass.

 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 :("Connectednnr".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();

    }

De Programm mécht de Serverport op, liest Donnéeën dovunner bis et e Kommando-End-Charakter begéint, passéiert de Kommando un en neie Prozess a leet den Ausgang vum Prozess an de Socket. Alles ass sou einfach wéi e Kalashnikov Attentat Gewier.

Deementspriechend gëtt et eng Iwwerlaaschtung fir dës Funktioun mat engem Standardport:

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

Gutt, deementspriechend ass d'Funktioun déi de Server stoppt och trivial, et ënnerbrach déi éiweg Loop, verletzt säin Zoustand.

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

Ech ginn hei keng Testklassen, si sinn hei ënnen - alles wat se maachen ass d'Funktionalitéit vun ëffentleche Methoden ze kontrolléieren. Alles ass op der Gitt.

Zesummefaassend, an e puer Owender kënnt Dir d'Prinzipien vun der Operatioun vun den Haaptkonsole Utilities verstoen. Elo, wa mir op e Ferncomputer telenet, verstinn mir wat geschitt - d'Magie ass verschwonnen)

Also, d'Links:
All Quelle waren, sinn a wäerten hei sinn
Iwwer Telnet
Méi iwwer Telnet

Source: will.com

Setzt e Commentaire