Java для чайников. Урок 35. Клиент серверное приложение. Продолжение - 2.
Автор megabax   
30.09.2017 г.
В этой статье я постараюсь максимально просто и понятно изложить основы программирования на языке Delphi

Java для чайников. Урок 35. Клиент серверное приложение. Продолжение - 2.

На прошлом уроке мы подробно разобрались с серверной частью нашего клиент-серверного приложения, которое создали на уроке Java для чайников. Урок 33. Клиент серверное приложение.

Итак, в клиентском приложении, как и в серверном, нам необходимо сначала подключить нужные библиотеки:

import java.io.*;

import java.net.*;

 

В процедуре main мы проверяем корректность командной строки, если она корректна, то создаем экземпляр класса клиента и передаем ему аргументы командной строки. Запускаем метод printQuotes, который  выводит полученный от сервера ответ на экран:

 

    /*

    Запуск приложения: проверка параметров командной строки, создание нужных объектов и прочее

    */

    public static void main(String args[]) {

        if(args.length<2)

        {

            System.out.println("Usage: StockQuoteClient <server> <stock ids>");

            System.exit(1);

        }

        StockQuoteClient client=new StockQuoteClient(args);

        client.printQuotes(System.out);

        System.exit(0);

    }

 

Посылка запроса на сервер и получение ответа происходит в конструкторе класса StockQuoteClient:

 

    //конструктор класса

    public StockQuoteClient(String[] args)

    {

        String serverInfo;

        serverName=args[0]; //первый параметр - имя сервера

       

        //размер массива на 1 меньше, чем args

        stockIDs = new String[args.length-1];

        stockInfo = new String[args.length-1];

       

        //скопируем аргументы в массив stocksIDs

        for(int index=1; index<args.length; index++)

        {

            stockIDs[index-1]=args[index];

        }

       

        serverInfo=contactServer(); //связаться с сервером и возвратить сообщение приветствия

       

        //распарсить строку с временем

        if(serverInfo!=null)

        {

            currentAsOf=serverInfo.substring(serverInfo.indexOf(" ")+1);

        }

        qetQuotes(); //считать информацию

        quitServer(); //закрыть соединение

    }

 

Что происходит в конструкторе? Сначала мы анализируем аргументы командной строки:

 

        String serverInfo;

        serverName=args[0]; //первый параметр - имя сервера

       

        //размер массива на 1 меньше, чем args

        stockIDs = new String[args.length-1];

        stockInfo = new String[args.length-1];

       

        //скопируем аргументы в массив stocksIDs

        for(int index=1; index<args.length; index++)

        {

            stockIDs[index-1]=args[index];

        }

 

Потом вызываем метод, который выполняет связь с сервером (contactServer):

serverInfo=contactServer(); //связаться с сервером и возвратить сообщение приветствия

 

Что он делает?

А он создает сокет для подключения к серверу и читает приглашение сервера:

 

    //соединиться с сервером

    protected String contactServer()

    {

        String serverWelcome=null; //приглашение сервера

        try

        {

            quoteSocket =  new Socket(serverName, SERVER_PORT); //открыть сокет на сервер

            quoteReceive = new DataInputStream(quoteSocket.getInputStream());

            quoteSend=new PrintStream(quoteSocket.getOutputStream());

            serverWelcome=quoteReceive.readLine(); //считать приглашение сервера

        } catch (IOException except)

        {

            System.err.println("Unknown host "+serverName+": "+except);

        }

        return serverWelcome; //вернуть приглашение сервера

    }

 

Таким образом, результат работы функции contactServer - это приглашение сервера. Что происходит дальше?

А дальше мы парсим полученный от сервера ответ (если, конечно, он получен):

 

        if(serverInfo!=null)

        {

            currentAsOf=serverInfo.substring(serverInfo.indexOf(" ")+1);

        }

 

Что делаем дальше? Считываем информацию и закрываем соединение:

        qetQuotes(); //считать информацию

        quitServer(); //закрыть соединение

 

Посмотрим, как устроена процедура чтения котировок:

    //считать информацию об акциях

    protected void qetQuotes()

    {

        String response; //ответ на запрос

       

        //если соединение в порядке

        if(connectOK())

        {

            try

            {

                //цикл по всем акциям

                for(int index=0; index<stockIDs.length; index++)

                {

                    if(stockIDs[index].indexOf("+")==0)

                    {

                        quoteSend.println(stockIDs[index].substring(1,stockIDs[index].length())); //послать запрос

                    }

                    else

                    {

                        quoteSend.println("STOCK: "+stockIDs[index]); //послать запрос

                    }

                    response=quoteReceive.readLine(); //получить ответ

                    stockInfo[index]=response.substring(response.indexOf(" ")+1); //распарсить полученные данные                   

                }

            } catch (IOException except)

            {

                System.err.println("Failed I/O to"+serverName+": "+except);

            }

        }

    }

 

Как она работает? Сначала мы при помощи вот такой небольшой процедуры проверяем, в  порядке ли соединение:

    //проверить, что с соединением все в порядке

    protected boolean connectOK()

    {

        return (quoteSend!=null && quoteReceive!=null && quoteSocket!=null);

    }

 

А дальше проверяем каждую акцию из массива, куда мы ранее загрузили их из командной строки. Как првоеряем? Посылаем запрос на сервер через объект quoteSend, который мы создали ранее и подключили к серверу.  А потом при помощи объекта quoteReceive получаем ответ. Объект quoteReceive мы тоже создали ранее и подключили его к серверу. Все это мы делаем в блоке обработки исключений.

Наконец, отключаемся от сервера:

    //отключение от сервера

    protected String quitServer()

    {

        String serverBuy=null; //сообщение отключения

        try

        {

            //если соединение в порядке

            if(connectOK())

            {  

                quoteSend.println("QUIT");

                serverBuy=quoteReceive.readLine();

            }

           

            //если ссылки не равны NULL, то надо закрыть потоки и сокет

            if(quoteSend!=null)  quoteSend.close();

            if(quoteReceive!=null) quoteReceive.close();

            if(quoteSocket!=null) quoteSocket.close();

           

        } catch (IOException except)

        {

            System.err.println("Failed I/O to "+serverName+": "+except);

        }

       

        return serverBuy;

    }

 

 

(С) Шуравин Александр