Windows mijoz-server yordam dasturlari bilan dasturiy ta'minotni yozish, 01-qism

Salomlar.

Bugun men sof Java-da Telnet, TFTP va boshqalar kabi standart Windows utilitlari funktsiyalarini bajaradigan mijoz-server ilovalarini yozish jarayonini ko'rib chiqmoqchiman. Men yangi hech narsa keltirmasligim aniq - bu kommunal xizmatlarning barchasi bir yildan ko'proq vaqt davomida muvaffaqiyatli ishlamoqda, ammo men ishonamanki, kaput ostida nima bo'layotganini hamma ham bilmaydi.

Aynan shu narsa kesma ostida muhokama qilinadi.

Ushbu maqolada, uni sudrab ketmaslik uchun, umumiy ma'lumotlarga qo'shimcha ravishda, men faqat Telnet serveri haqida yozaman, ammo hozirda boshqa yordamchi dasturlar haqida ham materiallar mavjud - bu seriyaning keyingi qismlarida bo'ladi.

Avvalo, siz Telnet nima ekanligini, u nima uchun kerakligini va nima uchun ishlatilishini aniqlab olishingiz kerak. Men manbalardan so'zma-so'z iqtibos keltirmayman (agar kerak bo'lsa, maqolaning oxirida mavzu bo'yicha materiallarga havolani qo'shaman), men faqat Telnet qurilmaning buyruq qatoriga masofadan kirishni ta'minlaydi, deb aytaman. Umuman olganda, uning funksionalligi shu erda tugaydi (men server portiga kirish haqida ataylab sukut saqladim; bu haqda keyinroq). Bu shuni anglatadiki, uni amalga oshirish uchun biz mijozdagi satrni qabul qilishimiz, uni serverga o'tkazishimiz, uni buyruq qatoriga o'tkazishga harakat qilishimiz, buyruq qatori javobini o'qishimiz, agar mavjud bo'lsa, uni mijozga qaytarishimiz va uni ekranda ko'rsating yoki xatolar bo'lsa, foydalanuvchiga nimadir noto'g'ri ekanligini bildiring.

Yuqoridagilarni amalga oshirish uchun, shunga ko'ra, bizga 2 ta ishchi sinf va serverni ishga tushiradigan va mijoz ishlaydigan ba'zi sinov sinfi kerak.
Shunga ko'ra, hozirgi vaqtda dastur tuzilmasi quyidagilarni o'z ichiga oladi:

  • TelnetClient
  • TelnetClientTester
  • Telnet Server
  • TelnetServerTester

Keling, ularning har birini ko'rib chiqaylik:

TelnetClient

Bu sinf qabul qilingan buyruqlarni yuborish va olingan javoblarni ko'rsatishi kerak. Bundan tashqari, siz masofaviy qurilmaning o'zboshimchalik (yuqorida aytib o'tilganidek) portiga ulanishingiz va undan uzishingiz kerak.

Bunga erishish uchun quyidagi funktsiyalar amalga oshirildi:

Argument sifatida rozetka manzilini oladigan, ulanishni ochadigan va kirish va chiqish oqimlarini boshlaydigan funksiya (oqim o'zgaruvchilari yuqorida e'lon qilingan, to'liq manbalar maqola oxirida).

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

Xuddi shu funktsiyani ortiqcha yuklash, standart portga ulanish - telnet uchun bu 23


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

Funktsiya klaviaturadan belgilarni o'qiydi va ularni chiqish rozetkasiga yuboradi - bu belgilar rejimida emas, balki chiziqli rejimda odatiy holdir:


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

Funktsiya rozetkadan ma'lumotlarni oladi va uni ekranda ko'rsatadi


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

Funktsiya ma'lumotlarni qabul qilish va uzatishni to'xtatadi


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

Telnet Server

Bu sinf rozetkadan buyruqni qabul qilish, uni bajarishga yuborish va buyruqdan javobni rozetkaga qaytarish funksiyasiga ega boβ€˜lishi kerak. Dastur ataylab kiritilgan ma'lumotlarni tekshirmaydi, chunki birinchidan, hatto "qutili telnet" da ham server diskini formatlash mumkin, ikkinchidan, ushbu maqolada xavfsizlik masalasi printsipial jihatdan olib tashlangan va shuning uchun ham yo'q. shifrlash yoki SSL haqida bir so'z.

Faqat ikkita funktsiya mavjud (ulardan biri haddan tashqari yuklangan) va umuman olganda, bu juda yaxshi amaliyot emas, lekin bu vazifani bajarish uchun hamma narsani avvalgidek qoldirish menga to'g'ri keldi.

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

    }

Dastur server portini ochadi, undagi ma'lumotlarni u buyruq yakuniy belgisiga duch kelmaguncha o'qiydi, buyruqni yangi jarayonga o'tkazadi va jarayondan chiqishni rozetkaga yo'naltiradi. Hammasi Kalashnikov avtomati kabi oddiy.

Shunga ko'ra, standart port bilan ushbu funktsiya uchun ortiqcha yuk mavjud:

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

Shunga ko'ra, serverni to'xtatuvchi funktsiya ham ahamiyatsiz bo'lib, uning holatini buzgan holda abadiy tsiklni to'xtatadi.

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

Men bu erda test darslarini bermayman, ular quyida - ular faqat ommaviy usullarning funksionalligini tekshirishadi. Hammasi gitda.

Xulosa qilib aytadigan bo'lsak, bir necha kechada siz asosiy konsol yordam dasturlarining ishlash tamoyillarini tushunishingiz mumkin. Endi biz masofaviy kompyuterga telenet qilganimizda, nima bo'layotganini tushunamiz - sehr yo'qoldi)

Shunday qilib, havolalar:
Barcha manbalar shu yerda bo'lgan, mavjud va bo'ladi
Telnet haqida
Telnet haqida batafsil

Manba: www.habr.com

a Izoh qo'shish