Parangkat lunak nyerat sareng fungsionalitas utilitas klien-server Windows, bagian 02

Nuluykeun runtuyan lumangsung artikel devoted kana palaksanaan custom utilitas konsol Windows, urang teu bisa mantuan tapi nyabak kana TFTP (Trivial File Transfer Protocol) - protokol mindahkeun file basajan.

Salaku panungtungan waktu, hayu urang sakeudeung balik leuwih téori, tingali kode nu implements fungsionalitas sarupa hiji diperlukeun, sarta analisa eta. Leuwih rinci - handapeun cut

Kuring moal nyalin-témpél informasi rujukan, numbu ka nu tradisional bisa kapanggih dina ahir artikel, Kuring ngan bakal nyebutkeun yén dina inti na, TFTP mangrupakeun variasi saderhana tina protokol FTP, nu setelan kontrol aksés boga. geus dihapus, sarta dina kanyataanana aya nanaon di dieu iwal paréntah pikeun narima jeung nransper file . Sanajan kitu, dina urutan sangkan palaksanaan urang saeutik leuwih elegan jeung diadaptasi kana prinsip ayeuna nulis kode, sintaksis geus rada robah - ieu teu ngarobah prinsip operasi, tapi panganteur, IMHO, janten saeutik leuwih logis tur ngagabungkeun aspék positif FTP jeung TFTP.

Khususna, nalika diluncurkeun, klien nyuhunkeun alamat IP pangladén sareng palabuhan dimana TFTP khusus dibuka (kusabab teu cocog sareng protokol standar, kuring nganggap éta pantes pikeun ngantepkeun pangguna pikeun milih palabuhan), saatos éta a sambungan lumangsung, salaku hasil nu klien bisa ngirim salah sahiji paréntah - meunang atawa nempatkeun, pikeun nampa atawa 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 kanyataan yén kelas tés ngan ukur aya pikeun debugging anu utama, kuring moal nganalisis aranjeunna, tapi kodeu bakal aya dina gudang; tautan kana éta tiasa dipendakan dina tungtung tulisan. Ayeuna kuring bakal ningali kelas utama.

TFTPClient

Tugas kelas ieu nyaéta pikeun nyambungkeun ka server jauh ku ip sareng nomer port na, maca paréntah tina aliran input (dina hal ieu, keyboard), parse, mindahkeun ka server, sareng, gumantung kana naha anjeun. kudu ngirim atawa nampa file, mindahkeun atawa meunang.

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 lengkep program. Kusabab triviality maranéhanana, kuring teu nyebut aranjeunna supados teu overload 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 balik ngaliwatan métode disebut dina blok kode ieu:

Di dieu file dikirim - ngagunakeun scanner a, urang nampilkeun eusi file salaku Asép Sunandar Sunarya ti bait, nu urang nulis hiji-hiji kana stop kontak, nu satutasna urang nutup sarta muka deui (sanes solusi paling atra, tapi). eta ngajamin sékrési sumberdaya), nu satutasna 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 retrieving data ti server. Sagalana deui trivial, ngan blok kahiji kode anu dipikaresep. Dina raraga ngartos persis sabaraha bait kudu maca tina stop kontak nu, anjeun kudu nyaho sabaraha beurat file ditransfer. Ukuran file dina server digambarkeun salaku integer panjang, jadi 4 bait ditarima di dieu, nu salajengna dirobah jadi hiji angka. Ieu sanes pendekatan Java pisan, éta rada sarupa pikeun SI, tapi solves masalah na.

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 lepat. Alatan triviality, abdi moal cutatan eta. Anu langkung narik nyaéta fungsi nampi sareng ngabagi senar input. Urang lulus scanner kana eta, ti mana urang ngaharepkeun pikeun nampa hiji garis dipisahkeun ku dua spasi tur 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 - ngirimkeun paréntah anu diasupkeun tina scanner ka stop kontak sareng maksakeun éta 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 mangrupikeun fungsi anu nangtukeun lampah program gumantung kana senar anu diasupkeun. Sagalana di dieu teu geulis pisan jeung trik dipaké teu pangalusna hiji kalawan kaluar kapaksa luar blok kode, tapi alesan utama ieu henteuna Java sababaraha hal, kawas delegasi dina C #, pointers fungsi tina C ++, atawa di. sahenteuna goto dahsyat na dahsyat, nu ngidinan Anjeun pikeun nerapkeun ieu beautifully. Lamun nyaho kumaha carana sangkan kode nu saeutik leuwih elegan, Kuring ngabagéakeun kritik dina komentar. Sigana mah kamus String-delegasi diperyogikeun di dieu, tapi henteu 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

Pungsi server béda ti pungsionalitas klien, sacara umum, ngan dina paréntah nu datang ka dinya teu ti keyboard, tapi ti stop kontak nu. Sababaraha metodeu umumna sami, janten kuring moal nyarioskeun aranjeunna, kuring ngan ukur nyabak kana bédana.

Pikeun ngamimitian, metoda ngajalankeun dipaké, nu narima port salaku input sarta ngolah data input ti stop kontak dina loop langgeng.

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

Metodeu nempatkeun, anu ngabungkus metode writeToFileFromSocket anu muka aliran nyerat kana file sareng nyerat sadaya bait input tina stop kontak, nunjukkeun pesen anu nunjukkeun parantosan transfer anu suksés nalika nyeratna 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 meunang retrieves file server. Sakumaha anu parantos disebatkeun dina bagian di sisi klien program, pikeun suksés nransferkeun file anjeun kedah terang ukuranana, disimpen dina integer anu panjang, janten kuring ngabagi kana sababaraha bait 4, mindahkeun bait-demi-bait. mun stop kontak nu, lajeng, sanggeus narima sarta dirakit aranjeunna dina klien kana angka deui, Kuring nransper sagala bait nu nyieun nepi file, maca ti stream input ti file.


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

Metodeu getAndParseInput sami sareng dina klien, ngan ukur bédana nyaéta maca data tina stop kontak tinimbang tina keyboard. Kodeu aya dina gudang, sapertos pamilih.
Dina hal ieu, initialization disimpen dina blok misah kode, sabab dina palaksanaan ieu, sanggeus mindahkeun geus réngsé, sumberdaya dileupaskeun sarta reoccupied deui - deui nyadiakeun 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:

Kami nembé nyerat variasi sorangan dina protokol transfer data anu saderhana sareng terang kumaha éta kedah dianggo. Sacara prinsip, kuring henteu mendakan Amérika di dieu sareng henteu nyerat seueur hal-hal anu énggal, tapi henteu aya tulisan anu sami ngeunaan Habré, sareng salaku bagian tina tulisan séri tulisan ngeunaan utilitas cmd mustahil henteu nyabak éta.

Rujukan:

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

sumber: www.habr.com

Tambahkeun komentar