Windows клиент-серверийн хэрэгслүүдийн функц бүхий програм хангамж бичих, 01-р хэсэг

Сайн байцгаана уу.

Өнөөдөр би Telnet, TFTP, гэх мэт Windows-ийн стандарт хэрэгслүүдийн үүргийг гүйцэтгэдэг клиент-сервер програмуудыг бичих үйл явцыг хармаар байна. Би ямар ч шинэ зүйл авчрахгүй нь тодорхой байна - эдгээр бүх хэрэгслүүд нэг жил гаруй хугацаанд амжилттай ажиллаж байгаа боловч бүрээсний доор юу болж байгааг хүн бүр мэддэггүй гэдэгт би итгэдэг.

Энэ бол яг л хасалтын хүрээнд яригдах зүйл юм.

Энэ нийтлэлд үүнийг чирэхгүйн тулд ерөнхий мэдээллээс гадна би зөвхөн Telnet серверийн талаар бичих болно, гэхдээ одоогоор бусад хэрэгслүүдийн талаархи материалууд байгаа - энэ нь цувралын цаашдын хэсгүүдэд байх болно.

Юуны өмнө та Telnet гэж юу болох, энэ нь юунд хэрэгтэй, юунд ашиглагддаг болохыг олж мэдэх хэрэгтэй. Би эх сурвалжийг үгчлэн иш татахгүй (хэрэв шаардлагатай бол нийтлэлийн төгсгөлд сэдэвтэй холбоотой материалын холбоосыг хавсаргана), би Telnet нь төхөөрөмжийн командын мөрөнд алсаас хандах боломжийг олгодог гэж л хэлэх болно. Ерөнхийдөө энд түүний функц дуусдаг (Би серверийн порт руу нэвтрэх талаар зориудаар чимээгүй байсан; энэ талаар дараа нь). Үүнийг хэрэгжүүлэхийн тулд бид клиент дээрх мөрийг хүлээн авч, сервер рүү дамжуулах, командын мөрөнд дамжуулахыг оролдох, тушаалын мөрийн хариултыг унших, хэрэв байгаа бол түүнийг буцааж клиент рүү дамжуулах хэрэгтэй гэсэн үг юм. дэлгэцэн дээр харуулах, эсвэл алдаа гарвал хэрэглэгчдэд ямар нэг зүйл буруу байгааг мэдэгдээрэй.

Дээр дурдсан зүйлийг хэрэгжүүлэхийн тулд бидэнд 2 ажлын анги, серверийг ажиллуулж, үйлчлүүлэгчээр дамжуулан ажиллах тестийн анги хэрэгтэй болно.
Үүний дагуу, одоогоор хэрэглээний бүтцэд дараахь зүйлс орно.

  • TelnetClient
  • TelnetClientTester
  • TelnetServer
  • TelnetServerTester

Тэдгээрийг тус бүрээр нь авч үзье:

TelnetClient

Энэ ангийн хийх ёстой бүх зүйл бол хүлээн авсан тушаалуудыг илгээх, хүлээн авсан хариултуудыг харуулах явдал юм. Нэмж дурдахад та алсын төхөөрөмжийн дурын (дээр дурдсанчлан) порт руу холбогдож, түүнээс салгах боломжтой байх хэрэгтэй.

Үүнд хүрэхийн тулд дараахь чиг үүргийг хэрэгжүүлэв.

Сокет хаягийг аргумент болгон авч, холболтыг нээж, оролт, гаралтын урсгалыг эхлүүлдэг функц (урсгалын хувьсагчдыг дээр зарласан, бүрэн эх сурвалжийг өгүүллийн төгсгөлд оруулсан болно).

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

TelnetServer

Энэ анги нь залгуураас команд хүлээн авах, гүйцэтгэхэд илгээх, командаас хариуг буцааж залгуур руу илгээх функцтэй байх ёстой. Хөтөлбөр нь оролтын өгөгдлийг зориудаар шалгадаггүй, учир нь нэгдүгээрт, "хайрцагтай telnet" дээр ч гэсэн серверийн дискийг форматлах боломжтой, хоёрдугаарт, энэ нийтлэл дэх аюулгүй байдлын асуудлыг зарчмын хувьд орхигдуулсан, тиймээс ч байхгүй. шифрлэлт эсвэл SSL-ийн тухай үг.

Зөвхөн 2 функц байдаг (тэдгээрийн нэг нь хэт ачаалалтай) бөгөөд ерөнхийдөө энэ нь тийм ч сайн туршлага биш боловч энэ даалгаврын үүднээс бүх зүйлийг байгаагаар нь үлдээх нь надад тохиромжтой юм шиг санагдаж байна.

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

    }

Програм нь серверийн портыг нээж, командын төгсгөлийн тэмдэгттэй тулгарах хүртэл түүнээс өгөгдлийг уншиж, тушаалыг шинэ процесс руу дамжуулж, процессоос гарсан гаралтыг залгуур руу дахин чиглүүлдэг. Калашниковын автомат буу шиг бүх зүйл энгийн.

Үүний дагуу анхдагч порттой энэ функцэд хэт ачаалал байна:

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

Үүний дагуу серверийг зогсоодог функц нь бас өчүүхэн бөгөөд энэ нь мөнхийн давталтыг тасалдуулж, нөхцөл байдлыг нь зөрчиж байна.

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

Би энд тестийн хичээлүүдийг өгөхгүй, тэд доор байна - тэдний хийдэг зүйл бол нийтийн аргуудын ажиллагааг шалгах явдал юм. Бүх зүйл гит дээр байна.

Дүгнэж хэлэхэд, хэд хэдэн үдшийн дараа та консолын үндсэн хэрэгслүүдийн ажиллах зарчмуудыг ойлгож чадна. Одоо бид алсын компьютерт теленет хийх үед юу болж байгааг ойлгож байна - ид шид алга болсон)

Тиймээс, холбоосууд:
Бүх эх сурвалж энд байсан, байгаа, байх болно
Telnet-ийн тухай
Telnet-ийн талаар дэлгэрэнгүй

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх