Nyieun perangkat lunak kalawan fungsi utilitas client-server Windows, bagian 02

Nuluykeun runtuyan artikel anu dikhususkeun pikeun implementasi khusus utilitas konsol Windows Mustahil teu nyebatkeun TFTP (Trivial File Transfer Protocol) - protokol transfer file anu saderhana.

Salaku panungtungan waktu, urang gé marios sakeudeung téori, kasampak di kode nu implements fungsionalitas sarupa hiji diperlukeun, sarta nganalisis eta. Langkung rinci di handap.

Abdi moal nyalin-témpél inpormasi rujukan, tautan anu sacara tradisional tiasa dipendakan dina tungtung tulisan. Kuring ngan bakal nyebutkeun yén TFTP dasarna mangrupakeun versi saderhana tina protokol ftp, nyoplokkeun setélan kontrol aksés jeung dasarna diwangun ku euweuh leuwih ti mindahkeun file na Paréntah dimeunangkeun. Tapi, sangkan palaksanaan urang saeutik leuwih elegan jeung adaptable kana prinsip coding modern, sintaksis geus rada dirobah. Ieu henteu ngarobih prinsip operasi, tapi antarmuka, dina pamanggih kuring, janten rada logis sareng ngagabungkeun aspék positip FTP sareng TFTP.

Husus, nalika diluncurkeun, klien naroskeun alamat IP pangladén sareng palabuhan dimana TFTP adat dibuka (kusabab teu cocog sareng protokol standar, panginten éta pantes pikeun ngantepkeun pilihan port ka pangguna). Sambungan teras diadegkeun, ngamungkinkeun klien pikeun ngirim salah sahiji paréntah — kéngingkeun atanapi nempatkeun — pikeun nyandak atanapi ngirim file ka server. Sadaya file dikirim dina modeu binér pikeun nyederhanakeun logika.

Pikeun nerapkeun protokol, kuring sacara tradisional ngagunakeun 4 kelas:

  • TFTPClient
  • TFTPServer
  • TFTPClientTester
  • TFTPServerTester

Kusabab kelas tés ngan ukur aya pikeun debugging kelas utama, kuring moal lebet kana éta. Kodeu bakal aya dina gudang; link ka eta bisa kapanggih dina tungtung artikel. Abdi badé nutupan kelas utama ayeuna.

TFTPClient

Tugas kelas ieu nyambung ka server jauh ku IP na port angka na, maca paréntah ti stream input (dina hal ieu, keyboard teh), parse eta, ngirimkeun ka server, sarta gumantung kana naha file perlu dikirimkeun atawa narima, ngirimkeun atawa nampa eta.

Kodeu pikeun ngaluncurkeun klien pikeun nyambung ka server sareng ngantosan paréntah tina aliran input sapertos kieu. Sajumlah variabel global anu dianggo di dieu dijelaskeun di luar artikel, dina téks program lengkep. Alatan triviality maranéhanana, abdi teu kaasup aranjeunna di dieu pikeun nyegah cluttering artikel.

 public void run(String ip, int port)
    {
        this.ip = ip;
        this.port = port;
        try {
            inicialization();
            Scanner keyboard = new Scanner(System.in);
            while (isRunning) {
                getAndParseInput(keyboard);
                sendCommand();
                selector();
                }
            }
        catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

Hayu urang ngajalankeun ngaliwatan métode disebut dina blok kode ieu:

Ieu dimana file dikirim-ngagunakeun alat panyeken, urang ngagambarkeun eusi file salaku Asép Sunandar Sunarya ti bait, nu urang nulis hiji-hiji kana stop kontak nu, lajeng nutup eta jeung buka deui (sanes solusi paling atra, tapi ngajamin sékrési sumberdaya), lajeng urang nembongkeun pesen ngeunaan mindahkeun suksés.

private  void put(String sourcePath, String destPath)
    {

        File src = new File(sourcePath);
        try {

            InputStream scanner = new FileInputStream(src);
            byte[] bytes = scanner.readAllBytes();
            for (byte b : bytes)
                sout.write(b);
            sout.close();
            inicialization();
            System.out.println("nDonen");
            }

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

sempalan kode ieu ngajelaskeun narima data ti server. Deui, sagalana geus trivial; ngan blok kahiji kode anu dipikaresep. Pikeun ngartos persis sabaraha bait anu kedah dibaca tina stop kontak, urang kedah terang ukuran file anu ditransfer. Ukuran file dina server digambarkeun salaku integer panjang, jadi opat bait katampi di dieu, nu salajengna dirobah jadi angka tunggal. Ieu sanés pendekatan sapertos Java; éta leuwih kawas pendekatan C-kawas, tapi meunang pakasaban rengse.

Lajeng sagalana geus trivial - urang nampi jumlah dipikawanoh tina bait ti stop kontak jeung nulis kana file, nu satutasna urang nembongkeun pesen suksés.

   private void get(String sourcePath, String destPath){
        long sizeOfFile = 0;
        try {


            byte[] sizeBytes = new byte[Long.SIZE];
           for (int i =0; i< Long.SIZE/Byte.SIZE; i++)
           {
               sizeBytes[i] = (byte)sin.read();
               sizeOfFile*=256;
               sizeOfFile+=sizeBytes[i];
           }

           FileOutputStream writer = new FileOutputStream(new File(destPath));
           for (int i =0; i < sizeOfFile; i++)
           {
               writer.write(sin.read());
           }
           writer.close();
           System.out.println("nDONEn");
       }
       catch (Exception e){
            System.out.println(e.getMessage());
       }
    }

Lamun paréntah lian ti "meunang" atawa "nempatkeun" ieu diasupkeun kana jandela klien, fungsi showErrorMessage bakal disebut, nunjukkeun yén input éta sah. Alatan triviality na, abdi moal kaasup. Fungsi pikeun narima jeung ngabagi string input rada leuwih metot. Urang lulus eta scanner, ti mana urang ngaharepkeun pikeun nampa string dipisahkeun ku dua spasi, ngandung paréntah, alamat sumber, jeung alamat tujuan.

    private void getAndParseInput(Scanner scanner)
    {
        try {

            input = scanner.nextLine().split(" ");
            typeOfCommand = input[0];
            sourcePath = input[1];
            destPath = input[2];
        }
        catch (Exception e) {
            System.out.println("Bad input");
        }
    }

Ngirim paréntah - mindahkeun paréntah diasupkeun ti scanner kana stop kontak jeung maksakeun ka dikirim

    private void sendCommand()
    {
        try {

            for (String str : input) {
                for (char ch : str.toCharArray()) {
                    sout.write(ch);
                }
                sout.write(' ');
            }
            sout.write('n');
        }
        catch (Exception e) {
            System.out.print(e.getMessage());
        }
    }

Pamilih nyaéta fungsi anu nangtukeun lampah program dumasar kana string input. Teu pisan elegan jeung ngagunakeun téhnik rada unsophisticated kode forcing kaluar blok, tapi alesan utama pikeun ieu nu Java lacks fitur nu tangtu, kawas delegasi dina C #, pointers fungsi dina C ++, atawa malah goto dreaded, nu bakal ngidinan pikeun palaksanaan leuwih elegan. Lamun nyaho kumaha carana sangkan kode nu saeutik leuwih elegan, mangga bagikeun pikiran anjeun dina komentar. Jigana kamus string-delegasi diperlukeun di dieu, tapi teu aya utusan ...

    private void selector()
    {
        do{
            if (typeOfCommand.equals("get")){
                get(sourcePath, destPath);
                break;
            }
            if (typeOfCommand.equals("put")){
                put(sourcePath, destPath);
                break;
            }
            showErrorMessage();
        }
        while (false);
    }
}

TFTPServer

fungsionalitas server urang béda ti fungsionalitas klien urang dasarna ngan dina paréntah nu narima via stop kontak tinimbang keyboard a. Sababaraha métode sabenerna sarua, jadi kuring moal nutupan aranjeunna di dieu; Kuring ngan bakal nyabak kana bédana.

Pikeun ngamimitian program, métode ngajalankeun dipaké, nu narima port salaku input sarta ngolah data input ti stop kontak dina loop taya wates.

    public void run(int port) {
            this.port = port;
            incialization();
            while (true) {
                getAndParseInput();
                selector();
            }
    }

Metoda nempatkeun, nu wraps metoda writeToFileFromSocket, muka stream nulis kana file jeung nulis sagala bait input ti stop kontak, sarta prints pesen ngeunaan parantosan sukses mindahkeun sanggeus nulis réngsé.

    private  void put(String source, String dest){
            writeToFileFromSocket();
            System.out.print("nDonen");
    };
    private void writeToFileFromSocket()
    {
        try {
            FileOutputStream writer = new FileOutputStream(new File(destPath));
            byte[] bytes = sin.readAllBytes();
            for (byte b : bytes) {
                writer.write(b);
            }
            writer.close();
        }
        catch (Exception e){
            System.out.println(e.getMessage());
        }
    }

Metodeu get retrieves file server. Sakumaha didadarkeun di bagian klien-sisi, mun hasil mindahkeun file, abdi peryogi kauninga ukuranana, disimpen salaku integer panjang. Ku alatan éta, kuring dibeulah jadi Asép Sunandar Sunarya 4-bait, mindahkeun éta bait ku bait kana stop kontak, lajeng, sanggeus narima eta na reassembling kana angka on klien nu, Kuring mindahkeun sakabéh bait nu nyieun nepi file, baca tina aliran input file urang.


 private  void get(String source, String dest){
        File sending = new File(source);
        try {
            FileInputStream readFromFile = new FileInputStream(sending);
            byte[] arr = readFromFile.readAllBytes();
            byte[] bytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(sending.length()).array();
            for (int i = 0; i<Long.SIZE / Byte.SIZE; i++)
                sout.write(bytes[i]);
            sout.flush();
            for (byte b : arr)
                sout.write(b);
        }
        catch (Exception e){
            System.out.println(e.getMessage());
        }
    };

Metoda getAndParseInput idéntik jeung métode klien urang, iwal mun maca data tina stop kontak tinimbang kibor. Kodeu aya dina gudang, sakumaha pamilih.
Dina hal ieu, initialization dipindahkeun ka blok misah kode, saprak dina kerangka palaksanaan ieu, sanggeus mindahkeun éta réngsé, sumberdaya dileupaskeun sarta ulang alokasi deui - deui guna mastikeun panyalindungan ngalawan leaks memori.

    private void  incialization()
    {
        try {
            serverSocket = new ServerSocket(port);
            socket = serverSocket.accept();
            sin = socket.getInputStream();
            sout = socket.getOutputStream();
        }
        catch (Exception e) {
            System.out.print(e.getMessage());
        }
    }

Pikeun nyimpulkeun:

Urang ngan nulis variasi sorangan dina protokol mindahkeun data basajan tur ilahar kaluar kumaha sakuduna jalan. Kuring teu bener megatkeun taneuh anyar dieu atawa ngomong nanaon utamana anyar, tapi aya teu wae artikel sarupa dina Habr, sarta salaku bagian tina runtuyan artikel ngeunaan Utiliti cmd, teu mungkin mun teu noél dina.

Rujukan:

Repository kode sumber
Sakeudeung ngeunaan TFTP
Hal anu sami, tapi dina basa Rusia

sumber: www.habr.com

Mésér hosting anu dipercaya pikeun situs anu gaduh panyalindungan DDoS, server VPS VDS 🔥 Meser hosting situs wéb anu tiasa dipercaya nganggo panyalindungan DDoS, server VPS VDS | ProHoster