Навиштани нармафзор бо функсияҳои утилитаҳои муштарӣ-сервери Windows, қисми 02

Идомаи силсилаи ҷории мақолаҳое, ки ба татбиқи фармоишии утилитаҳои консолии Windows бахшида шудаанд, мо наметавонем ба TFTP (Trivial Transfer Protocol) - протоколи оддии интиқоли файл муроҷиат кунем.

Чун дафъаи гузашта, биёед ба таври мухтасар назарияро дида бароем, кодеро бубинем, ки функсияи шабеҳи лозимиро амалӣ мекунад ва онро таҳлил мекунад. Тафсилоти бештар - дар зери набуред

Ман маълумоти истинодро нусхабардорӣ намекунам, ки истиноди онҳоро одатан дар охири мақола пайдо кардан мумкин аст, ман танҳо мегӯям, ки TFTP дар асл як варианти соддакардашудаи протоколи FTP мебошад, ки дар он танзимоти назорати дастрасӣ дорад нест карда шудааст ва дар асл дар ин ҷо ҷуз фармонҳо барои қабул ва интиқоли файл чизе нест. Аммо, барои он ки татбиқи мо каме шевотар ва ба принсипҳои кунунии навиштани код мутобиқ карда шавад, синтаксис каме тағир дода шуд - ин принсипҳои корро тағир намедиҳад, аммо интерфейс, IMHO, каме мантиқӣ ва мантиқӣ мешавад. ҷанбаҳои мусбати FTP ва TFTP -ро муттаҳид мекунад.

Аз ҷумла, ҳангоми оғозёбӣ, муштарӣ суроғаи IP-и сервер ва бандаре, ки дар он TFTP фармоишӣ кушода аст, дархост мекунад (аз сабаби номувофиқатӣ бо протоколи стандартӣ, ман мувофиқ донистам, ки ба корбар имкони интихоби портро гузорам), пас аз он пайвастшавӣ ба амал меояд, ки дар натиҷа муштарӣ метавонад яке аз фармонҳоро фиристад - гирифтан ё гузоштан, қабул ё фиристодани файл ба сервер. Барои содда кардани мантиқ ҳама файлҳо дар реҷаи дуӣ фиристода мешаванд.

Барои татбиқи протокол, ман маъмулан 4 синфро истифода мебурдам:

  • TFTPClient
  • TFTPSсервер
  • TFTPClientTester
  • TFTPServerTester

Аз сабаби он, ки синфҳои санҷишӣ танҳо барои ислоҳи синфҳои асосӣ вуҷуд доранд, ман онҳоро таҳлил намекунам, аммо код дар анбор хоҳад буд; истиноди онро дар охири мақола пайдо кардан мумкин аст. Акнун ман ба синфҳои асосӣ назар хоҳам дод.

TFTPClient

Вазифаи ин синф пайваст шудан ба сервери дурдаст бо рақами IP ва порт, хондани фармон аз ҷараёни вуруд (дар ин ҳолат, клавиатура), таҳлили он, интиқол додани он ба сервер ва вобаста ба он, ки шумо фиристодан ё гирифтани файл, интиқол ё гирифтани он лозим аст.

Рамзи оғоз кардани муштарӣ барои пайвастшавӣ ба сервер ва интизор шудани фармон аз ҷараёни вуруд чунин менамояд. Як қатор тағирёбандаҳои глобалӣ, ки дар ин ҷо истифода мешаванд, берун аз мақола, дар матни пурраи барнома тавсиф карда шудаанд. Ба далели ночиз будани онҳо, ман онҳоро истинод намекунам, то мақоларо аз ҳад зиёд пур накунам.

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

Биёед усулҳои дар ин блоки код номбаршударо дида бароем:

Дар ин ҷо файл фиристода мешавад - бо истифода аз сканер, мо мундариҷаи файлро ҳамчун массиви байтҳо пешниҳод мекунем, ки мо онро як ба як ба розетка менависем ва пас аз он онро мепӯшем ва боз мекушоем (на ҳалли равшантарин, балки он озод кардани захираҳоро кафолат медиҳад), пас аз он мо дар бораи интиқоли муваффақ паём нишон медиҳем.

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

Ин порчаи код гирифтани маълумотро аз сервер тавсиф мекунад. Ҳама чиз боз ночиз аст, танҳо блоки якуми код таваҷҷӯҳ дорад. Барои дақиқ фаҳмидани он, ки аз розетка чанд байт хондан лозим аст, шумо бояд бидонед, ки вазни файли интиқолшуда чӣ қадар аст. Андозаи файл дар сервер ҳамчун як адади дароз нишон дода мешавад, бинобар ин дар ин ҷо 4 байт қабул карда мешавад, ки баъдан ба як адад табдил дода мешаванд. Ин як равиши Java нест, он барои SI хеле монанд аст, аммо он мушкилоти худро ҳал мекунад.

Он гоҳ ҳама чиз ночиз аст - мо аз розетка миқдори маълуми байтҳоро мегирем ва онҳоро ба файл менависем, пас аз он мо паёми муваффақиятро нишон медиҳем.

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

Агар ба равзанаи муштарӣ фармони ғайр аз get ё put ворид шуда бошад, функсияи showErrorMessage даъват карда мешавад, ки ин хато будани вурудро нишон медиҳад. Аз сабаби ночизӣ, ман онро истинод намекунам. То ҳадде ҷолибтар вазифаи қабул ва тақсим кардани сатри вуруд аст. Мо сканерро ба он мегузорем, ки аз он интизорем, ки сатри бо ду фосила ҷудошуда ва дорои фармон, суроғаи манбаъ ва суроғаи таъинотро қабул кунем.

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

Фиристодани фармон — фармони аз сканер воридшударо ба розетка интиқол медиҳад ва барои фиристодан маҷбур мекунад

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

Селектор функсияест, ки амали барномаро вобаста ба сатри воридшуда муайян мекунад. Ҳама чиз дар ин ҷо чандон зебо нест ва ҳилае, ки истифода мешавад, беҳтарин роҳи баромадани маҷбурӣ берун аз блоки код нест, аммо сабаби асосии ин мавҷуд набудани баъзе чизҳо дар Java мебошад, ба монанди намояндагон дар C#, нишондиҳандаҳои функсия аз C++ ё дар ҳадди аққал гото даҳшатнок ва даҳшатнок, ки ба шумо имкон медиҳад, ки инро зебо иҷро кунед. Агар шумо медонед, ки чӣ гуна кодро каме шевотар созед, ман танқидро дар шарҳҳо истиқбол мекунам. Ба назари ман, дар ин ҷо луғати String-delegate лозим аст, аммо вакил нест...

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

TFTPSсервер

Функсияи сервер аз функсияи мизоҷ ба андозаи калон танҳо дар он аст, ки фармонҳо ба он на аз клавиатура, балки аз розетка меоянд. Баъзе усулҳо умуман якхелаанд, бинобар ин ман онҳоро иқтибос намекунам, ман танҳо ба фарқиятҳо дахл мекунам.

Барои оғоз кардан, усули иҷро истифода мешавад, ки портро ҳамчун вуруд қабул мекунад ва маълумоти воридшударо аз розетка дар як ҳалқаи абадӣ коркард мекунад.

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

Усули put, ки усули writeToFileFromSocket-ро фаро мегирад, ки ҷараёни навиштанро ба файл мекушояд ва ҳамаи байтҳои вурудро аз васлаки васл мекунад, паёмеро нишон медиҳад, ки ҳангоми анҷоми навиштан анҷоми бомуваффақияти интиқолро нишон медиҳад.

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

Усули get файли серверро дарёфт мекунад. Тавре ки аллакай дар бахши муштарии барнома зикр шудааст, барои бомуваффақият интиқол додани файл шумо бояд андозаи онро донед, ки дар як адади дароз нигоҳ дошта мешавад, бинобар ин ман онро ба массиви 4 байт тақсим мекунам, онҳоро байт ба байт интиқол медиҳам. ба розетка, ва он гоҳ, ки онҳоро дар мизоҷ қабул ва ҷамъ ба як рақами баргашт, ман ҳамаи байтҳои, ки файл ташкил, интиқол аз ҷараёни вуруди аз файл хонда.


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

Усули getAndParseInput ҳамон тавре ки муштарӣ аст, ягона фарқият дар он аст, ки он маълумотро на аз клавиатура аз розетка мехонад. Рамз дар анбор аст, мисли селектор.
Дар ин ҳолат, инициализатсия дар блоки алоҳидаи код ҷойгир карда мешавад, зеро дар доираи ин татбиқ, пас аз анҷоми интиқол, захираҳо озод карда мешаванд ва дубора ишғол карда мешаванд - боз барои муҳофизат аз ихроҷи хотира.

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

Барои ҷамъбаст:

Мо танҳо варианти худро дар протоколи оддии интиқоли маълумот навиштем ва фаҳмидем, ки он чӣ гуна бояд кор кунад. Аслан, ман Амрикоро дар ин ҷо кашф накардаам ва чизҳои нав нанавиштам, аммо дар бораи Ҳабре мақолаҳои шабеҳ набуданд ва ҳамчун як қисми навиштани як қатор мақолаҳо дар бораи utilities cmd ба он дахл накардан ғайриимкон буд.

Истинодҳо:

Анбори рамзи манбаъ
Мухтасар дар бораи TFTP
Ҳамин чиз, аммо ба забони русӣ

Манбаъ: will.com

Илова Эзоҳ