Windowsi klient-server utiliitidega tarkvara kirjutamine, osa 01

Tere.

TĂ€na tahaksime arutada kliendi-serveri rakenduste kirjutamise protsessi, mis tĂ€idavad Windowsi standardsete utiliitide funktsioone nagu Telnet, TFTP jne, puhtas Javaski. On selge, et ma ei too midagi uut — kĂ”ik need utiliidid on juba aastaid edukalt töötanud, kuid arvan, et mitte kĂ”ik ei tea, mis nende taga toimub.

Just sellest juttu tuleb.

Selles artiklis, et mitte seda venitada, kirjutan ma ainult Telnet serverist, kuid hetkel on ka teisi utiliite, mille kohta on materjali — need tulevad hiljem sarja jĂ€rgmistes osades.

Esiteks, tuleks aru saada, mis on Telnet, milleks seda vaja on ja kuidas sellega ĂŒmber kĂ€ia. Ma ei hakka allikaid sĂ”na-sĂ”nalt tsiteerima (kui vaja — lisatakse artikli lĂ”pus lingid teemale), ĂŒtlen vaid, et Telnet vĂ”imaldab kaugjuurdepÀÀsu seadme kĂ€sureale. Suures osas sellega tema funktsionaalsus lĂ”peb (serveri pordi juurde pÀÀsemisest ma praegu ei rÀÀgi, sellest hiljem). Seega, selle rakendamiseks peame klientide kaudu vĂ”tma andmearmu, edastama selle serverisse, proovima seda kĂ€sureale edastada, lugema kĂ€surea vastuse, kui see on olemas, edastama selle tagasi kliendile ja kuvama ekraanile vĂ”i, kui tekib viga, teavitama kasutajat, et midagi on valesti.

Selleks on vastavalt vaja kahte töötavat klassi ja ĂŒhte testimis klassi, mille kaudu me serverit kĂ€ivitame ja mille kaudu klient töötab.
Seega praeguse seisuga sisaldab rakenduse struktuur:

  • TelnetClient
  • TelnetClientTester
  • TelnetServer
  • TelnetServerTester

Vaatame igaĂŒht neist lĂ€hemalt:

TelnetClient

KĂ”ik, mida see klass peaks oskama teha — edastada saadud kĂ€ske ja nĂ€idata saadud vastuseid. Lisaks peab olema vĂ”imalik ĂŒhendada vĂ€gisi (nagu mainitud) kaugseadme pordiga ja sellest lahti ĂŒhenduda.

Selleks on rakendatud jÀrgmised funktsioonid:

Funktsioon, mis vĂ”tab argumendiks pordi aadressi, avab ĂŒhenduse ja kĂ€ivitab sisendi ja vĂ€ljundi voogude (voo muutujad on mÀÀratud eespool, tĂ€ielikud lĂ€htekoodid — artikli lĂ”pus).

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

Sama funktsiooni ĂŒlekoormamine, mis ĂŒhendub vaikimisi pordiga — telnet jaoks on see 23


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

Funktsioon loeb klaviatuurilt mĂ€rke ja saadab need vĂ€ljundpessa — nagu tavaks, reamoodulisse, mitte tĂ€hemĂ€rkimoodulisse:


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

Funktsioon vÔtab andmeid soketist ja kuvab need ekraanile


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

Funktsioon lÔpetab andmete vastuvÔtmise ja edastamise


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

TelnetServer

See klass peaks olema vĂ”imeline vĂ”tma kĂ€ske soketist, saatma need tĂ€itmiseks ja edastama vastuse kĂ€sust tagasi soketisse. Programmis ei ole teadlikult sissekandeid kontrollimist, kuna esiteks on 'karbitelevisioonis' vĂ”imalik ketast formaadida ning teiseks, turvakĂŒsimust ei kĂ€sitleta selles artiklis ĂŒldse ja seetĂ”ttu ei ole siin ĂŒhtegi sĂ”na krĂŒpteerimise vĂ”i SSL-i kohta.

Siin on ainult 2 funktsiooni (ĂŒks neist on ĂŒlekoormatud), ja see ei ole ĂŒldiselt hea praktika, kuid antud ĂŒlesande raames tundus mĂ”istlik jĂ€tta kĂ”ik nii nagu on.

 boolean isRunning = true;
    public void run(int port)    {

        (new Thread(()->{ try {
            ServerSocket ss = new ServerSocket(port); // loome serveri soketi ja seome selle ĂŒlaltoodud sadamaga
            System.out.println("Port " + port + " on ootamas ĂŒhendusi");

            Socket socket = ss.accept();
            System.out.println("Ühendatud");
            System.out.println();

            // Saame sissetulevad ja vĂ€ljaminevad soketi vood, nĂŒĂŒd saame klientidele andmeid edastada.
            InputStream sin = socket.getInputStream();
            OutputStream sout = socket.getOutputStream();

            Map 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 = "Midagi lÀks valesti... Viga kood: " + 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("Viga: " + e.getMessage());
                    }
                }).start();
                System.out.println(buffer);
                buffer = "";

            }
        }
        catch(Exception x) {
            System.out.println(x.getMessage());
        }})).start();

    }

Programm avab serveri porta, loeb andmeid, kuni jĂ”uab kĂ€su lĂ”petamise sĂŒmbolini, edastab kĂ€su uude protsessi ja selle vĂ€ljund suunatakse soketti. KĂ”ik on sama lihtne nagu KalaĆĄnikovi automaat.

Seega on selle funktsiooni jaoks olemas ĂŒlekload vaikeportiga:

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

Ja seega on ka serveri peatamise funktsioon - kĂ”ik on samuti triviaalne, see katkestab igavese tsĂŒkli, rikkudes selle tingimust.

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

Ma ei hakka siin nĂ€itama testklasse, need on all — kĂ”ik, mida nad teevad, on kontrollida avalike meetodite töövĂ”imet. KĂ”ik on Gitis.

KokkuvĂ”tteks, paaril Ă”htul on vĂ”imalik mĂ”ista peamiste konsoolikasutustest tulenevaid pĂ”himĂ”tteid. NĂŒĂŒd, kui meil on telnet koos kaugolekuga, mĂ”istame, mis toimub — maagia on kadunud)

Nii et, lingid:
KÔik lÀhtekoodid on, olid ja jÀÀvad siia
Telnetist
Veel Telnetist

Allikas: habr.com

Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster