Pagsulat sa software nga adunay gamit sa Windows client-server utilities, bahin 02

Nagpadayon sa nagpadayon nga serye sa mga artikulo nga gipahinungod sa naandan nga pagpatuman sa Windows console utilities, dili kami makapugong sa paghikap sa TFTP (Trivial File Transfer Protocol) - usa ka yano nga file transfer protocol.

Sama sa miaging higayon, atong hisgotan sa makadiyot ang teorya, tan-awa ang code nga nagpatuman sa pagpaandar nga parehas sa gikinahanglan, ug analisa kini. Dugang nga mga detalye - ubos sa pagputol

Dili ko kopyahon-paste ang impormasyon sa pakisayran, mga link nga tradisyonal nga makit-an sa katapusan sa artikulo, isulti ko lang nga sa kinauyokan niini, ang TFTP usa ka gipasimple nga pagbag-o sa FTP protocol, diin ang setting sa kontrol sa pag-access adunay gikuha, ug sa pagkatinuod walay bisan unsa dinhi gawas sa mga sugo alang sa pagdawat ug pagbalhin sa usa ka file . Bisan pa, aron mahimo ang among pagpatuman nga labi ka elegante ug gipahiangay sa karon nga mga prinsipyo sa pagsulat sa code, ang syntax gamay nga nabag-o - wala kini magbag-o sa mga prinsipyo sa operasyon, apan ang interface, IMHO, nahimo nga labi ka makatarunganon ug naghiusa sa mga positibo nga aspeto sa FTP ug TFTP.

Sa partikular, kung gilansad, ang kliyente nangayo sa IP address sa server ug ang pantalan diin ang naandan nga TFTP bukas (tungod sa dili pagkauyon sa sumbanan nga protocol, giisip nako nga angay nga biyaan ang tiggamit sa katakus sa pagpili sa usa ka pantalan), pagkahuman usa ka koneksyon mahitabo, ingon sa usa ka resulta nga ang kliyente makapadala sa usa sa mga sugo - pagkuha o ibutang, sa pagdawat o pagpadala sa usa ka file ngadto sa server. Ang tanan nga mga file gipadala sa binary mode aron pasimplehon ang lohika.

Aron ipatuman ang protocol, naandan nako nga gigamit ang 4 nga mga klase:

  • TFTPClient
  • TFTPServer
  • TFTPClientTester
  • TFTPServerTester

Tungod sa kamatuoran nga ang mga klase sa pagsulay anaa lamang alang sa pag-debug sa mga nag-una, dili ko kini analisahon, apan ang code anaa sa repository; usa ka link niini makita sa katapusan sa artikulo. Karon akong tan-awon ang mga nag-unang klase.

TFTPClient

Ang tahas niini nga klase mao ang pagkonektar sa usa ka hilit nga server pinaagi sa numero sa ip ug port niini, pagbasa sa usa ka command gikan sa input stream (sa kini nga kaso, ang keyboard), pag-parse niini, pagbalhin niini ngadto sa server, ug, depende kung ikaw kinahanglan nga magpadala o makadawat og file, ibalhin kini o kuhaon.

Ang code alang sa paglansad sa kliyente aron makonektar sa server ug maghulat alang sa usa ka mando gikan sa input stream ingon niini. Daghang mga global variable nga gigamit dinhi gihulagway sa gawas sa artikulo, sa tibuuk nga teksto sa programa. Tungod sa ilang kawalay pulos, wala nako sila gikutlo aron dili ma-overload ang artikulo.

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

Atong susihon ang mga pamaagi nga gitawag niini nga block sa code:

Dinhi gipadala ang file - gamit ang usa ka scanner, gipresentar namon ang sulud sa file ingon usa ka han-ay sa mga byte, nga among isulat sa usag usa sa socket, pagkahuman gisirhan namon kini ug giablihan kini pag-usab (dili ang labing klaro nga solusyon, apan gigarantiyahan niini ang pagpagawas sa mga kapanguhaan), pagkahuman nagpakita kami usa ka mensahe bahin sa malampuson nga pagbalhin.

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

Kini nga code fragment naghulagway sa pagkuha sa data gikan sa server. Ang tanan wala’y hinungdan pag-usab, ang una nga bloke sa code ang interesado. Aron masabtan kung pila ka mga byte ang kinahanglan basahon gikan sa socket, kinahanglan nimo mahibal-an kung unsa ang gibug-aton sa gibalhin nga file. Ang gidak-on sa file sa server girepresentahan ingon nga usa ka taas nga integer, mao nga 4 bytes ang gidawat dinhi, nga pagkahuman gibag-o sa usa ka numero. Dili kini usa ka pamaagi sa Java, parehas kini sa SI, apan gisulbad niini ang problema niini.

Unya ang tanan gamay ra - nakadawat kami usa ka nahibal-an nga gidaghanon sa mga byte gikan sa socket ug isulat kini sa usa ka file, pagkahuman nagpakita kami usa ka mensahe sa kalampusan.

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

Kung ang usa ka sugo gawas sa pagkuha o ibutang ang gisulod sa bintana sa kliyente, ang showErrorMessage function tawgon, nga nagpakita nga ang input dili husto. Tungod sa triviality, dili nako kini i-cite. Medyo mas makapaikag mao ang function sa pagdawat ug pagbahin sa input string. Gipasa namo ang scanner ngadto niini, diin kami nagpaabot nga makadawat og linya nga gibulag sa duha ka mga luna ug naglangkob sa sugo, tinubdan nga adres ug destinasyon nga adres.

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

Pagpadala og sugoβ€”nagpadala sa sugo nga gisulod gikan sa scanner ngadto sa socket ug gipugos kini nga ipadala

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

Ang usa ka tigpili usa ka function nga nagtino sa mga aksyon sa programa depende sa gisulod nga string. Ang tanan dinhi dili kaayo nindot ug ang lansis nga gigamit dili ang pinakamaayo nga adunay pinugos nga paggawas sa gawas sa code block, apan ang nag-unang rason niini mao ang pagkawala sa Java sa pipila ka mga butang, sama sa mga delegado sa C #, function pointers gikan sa C++, o sa labing gamay ang makalilisang ug makalilisang nga goto, nga nagtugot kanimo sa pagpatuman niini nga matahum. Kung nahibal-an nimo kung giunsa ang paghimo sa code nga labi ka elegante, gidawat nako ang pagsaway sa mga komento. Para nako gikinahanglan ang usa ka diksyonaryo sa String-delegate dinhi, apan walay delegado...

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

TFTPServer

Ang pag-andar sa server lahi sa pag-andar sa kliyente, sa kadaghanan, sa kana nga mga mando moabut dili gikan sa keyboard, apan gikan sa socket. Ang pipila sa mga pamaagi sa kasagaran managsama, mao nga dili ko kini hisgotan, hikap ra nako ang mga kalainan.

Sa pagsugod, gigamit ang pamaagi sa pagdagan, nga nakadawat usa ka pantalan ingon input ug giproseso ang data sa input gikan sa socket sa usa ka walay katapusan nga loop.

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

Ang put method, nga nagputos sa writeToFileFromSocket method nga nagbukas sa write stream ngadto sa file ug nagsulat sa tanang input bytes gikan sa socket, nagpakita ug mensahe nga nagpakita sa malampusong pagkompleto sa transfer kung makompleto na ang pagsulat.

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

Ang get method nagkuha sa server file. Sama sa nahisgutan na sa seksyon sa bahin sa kliyente sa programa, aron malampuson nga mabalhin ang usa ka file kinahanglan nimo mahibal-an ang gidak-on niini, nga gitipigan sa usa ka taas nga integer, mao nga gibahin nako kini sa usa ka han-ay sa 4 byte, ibalhin sila byte-by-byte ngadto sa socket, ug unya, nga nakadawat ug nagtigum kanila sa kliyente ngadto sa usa ka numero balik, akong gibalhin ang tanan nga mga byte nga naglangkob sa file, gibasa gikan sa input stream gikan sa 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());
        }
    };

Ang getAndParseInput nga pamaagi parehas sa kliyente, ang kalainan mao nga kini nagbasa sa datos gikan sa socket kaysa sa keyboard. Ang code anaa sa repository, sama sa selector.
Sa kini nga kaso, ang pagsugod gibutang sa usa ka bulag nga bloke sa code, tungod kay sulod niini nga implementasyon, human makompleto ang pagbalhin, ang mga kahinguhaan gibuhian ug gi-okupar pag-usab - pag-usab aron paghatag og proteksyon batok sa mga pagtulo sa memorya.

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

Sa pag-summarize:

Bag-o lang namon gisulat ang among kaugalingon nga kalainan sa usa ka yano nga protocol sa pagbalhin sa datos ug nahibal-an kung giunsa kini molihok. Sa prinsipyo, wala nako nadiskobrehan ang America dinhi ug wala magsulat og daghang bag-ong mga butang, apan walay susama nga mga artikulo sa HabrΓ©, ug isip kabahin sa pagsulat sa usa ka serye sa mga artikulo mahitungod sa cmd utilities imposible nga dili mahikap niini.

Mga reperensiya:

Repository sa source code
Sa mubo bahin sa TFTP
Ang sama nga butang, apan sa Russian

Source: www.habr.com

Idugang sa usa ka comment