Kuandika programu yenye utendaji wa huduma za seva ya mteja wa Windows, sehemu ya 01

Salamu.

Leo ningependa kuangalia mchakato wa kuandika maombi ya seva ya mteja ambayo hufanya kazi za huduma za kawaida za Windows, kama vile Telnet, TFTP, et cetera, et cetera katika Java safi. Ni wazi kuwa sitaleta chochote kipya - huduma hizi zote zimekuwa zikifanya kazi kwa mafanikio kwa zaidi ya mwaka mmoja, lakini ninaamini sio kila mtu anajua kinachoendelea chini ya kofia.

Hii ndio hasa itajadiliwa chini ya kukata.

Katika nakala hii, ili sio kuiondoa, pamoja na habari ya jumla, nitaandika tu juu ya seva ya Telnet, lakini kwa sasa kuna nyenzo kwenye huduma zingine - itakuwa katika sehemu zaidi za safu.

Kwanza kabisa, unahitaji kujua Telnet ni nini, inahitajika kwa nini, na inatumika kwa nini. Sitanukuu vyanzo vya maneno (ikiwa ni lazima, nitaunganisha kiunga cha nyenzo kwenye mada mwishoni mwa kifungu), nitasema tu kwamba Telnet hutoa ufikiaji wa mbali kwa safu ya amri ya kifaa. Kwa ujumla, hapa ndipo utendakazi wake unaisha (nilinyamaza kimakusudi kuhusu kupata bandari ya seva; zaidi juu ya hilo baadaye). Hii ina maana kwamba ili kutekeleza, tunahitaji kukubali mstari kwa mteja, kuipitisha kwa seva, jaribu kuipitisha kwa mstari wa amri, soma majibu ya mstari wa amri, ikiwa kuna moja, uirudishe kwa mteja na. ionyeshe kwenye skrini, au, ikiwa makosa, basi mtumiaji ajue kuwa kuna kitu kibaya.

Ili kutekeleza yaliyo hapo juu, ipasavyo, tunahitaji madarasa 2 ya kufanya kazi na darasa la mtihani ambalo tutazindua seva na kupitia ambayo mteja atafanya kazi.
Ipasavyo, kwa sasa muundo wa maombi ni pamoja na:

  • TelnetClient
  • TelnetClientTester
  • TelnetServer
  • TelnetServerTester

Wacha tupitie kila mmoja wao:

TelnetClient

Kila darasa hili linafaa kuwa na uwezo wa kufanya ni kutuma amri zilizopokelewa na kuonyesha majibu yaliyopokelewa. Kwa kuongeza, unahitaji kuwa na uwezo wa kuunganisha kwenye bandari ya kiholela (kama ilivyoelezwa hapo juu) ya kifaa cha mbali na uondoe kutoka kwayo.

Ili kufanikisha hili, kazi zifuatazo zilitekelezwa:

Chaguo za kukokotoa ambazo huchukua anwani ya tundu kama hoja, hufungua muunganisho na kuanza mitiririko ya ingizo na utoaji (vigezo vya mtiririko vimetangazwa hapo juu, vyanzo kamili viko mwishoni mwa makala).

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

Kupakia kazi sawa, kuunganisha kwa mlango chaguo-msingi - kwa telnet hii ni 23


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

Kazi husoma herufi kutoka kwa kibodi na kuzituma kwa tundu la pato - ambalo ni la kawaida, katika hali ya mstari, sio hali ya herufi:


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

Kazi hupokea data kutoka kwa tundu na kuionyesha kwenye skrini


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

Chaguo za kukokotoa husimamisha upokeaji na usambazaji wa data


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

TelnetServer

Darasa hili lazima liwe na utendaji wa kupokea amri kutoka kwa tundu, kuituma kwa utekelezaji, na kutuma jibu kutoka kwa amri kwenye tundu. Mpango huo hauangalii data ya pembejeo kwa makusudi, kwa sababu kwanza, hata katika "boxed telnet" inawezekana kuunda diski ya seva, na pili, suala la usalama katika makala hii limeachwa kwa kanuni, na ndiyo sababu hakuna. neno kuhusu usimbaji fiche au SSL.

Kuna kazi 2 tu (moja yao imejaa), na kwa ujumla hii sio mazoezi mazuri sana, lakini kwa madhumuni ya kazi hii, ilionekana kuwa sawa kwangu kuacha kila kitu kama ilivyo.

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

    }

Programu inafungua bandari ya seva, inasoma data kutoka kwake hadi itakapokutana na tabia ya mwisho ya amri, kupitisha amri kwa mchakato mpya, na kuelekeza pato kutoka kwa mchakato hadi kwenye tundu. Kila kitu ni rahisi kama bunduki ya kushambulia ya Kalashnikov.

Ipasavyo, kuna upakiaji mwingi wa chaguo hili la kukokotoa na lango chaguo-msingi:

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

Naam, ipasavyo, kazi ambayo inasimamisha seva pia ni ndogo, inasumbua kitanzi cha milele, kukiuka hali yake.

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

Sitatoa darasa za majaribio hapa, ziko hapa chini - wanachofanya ni kuangalia utendakazi wa mbinu za umma. Kila kitu kiko kwenye git.

Kwa muhtasari, katika jioni kadhaa unaweza kuelewa kanuni za uendeshaji wa huduma kuu za koni. Sasa, tunapotuma simu kwa kompyuta ya mbali, tunaelewa kinachotokea - uchawi umetoweka)

Kwa hivyo, viungo:
Vyanzo vyote vilikuwa, vipo na vitakuwa hapa
Kuhusu Telnet
Pata maelezo zaidi kuhusu Telnet

Chanzo: mapenzi.com

Kuongeza maoni