Rubyn: различия между версиями

6 байт добавлено ,  2 года назад
Как мы уже видели выше, серверная часть полностью определяет функциональность всего клиент-серверного приложения. Клиентская часть же лишь принимает от пользователя запросы, пересылает их серверу и получает ответ, который передает пользователю.
 
Хотя Geka и имел в своем распоряжении клиентскую программу, ее мы рассматривать не будем, так как с тех пор его сервер претерпел некоторые изменения и прежняя клиентская часть не может работать с нынешней серверной. Мы напишем новую клиенскуюклиентскую часть «с нуля».
 
Для соединения с сервером по протоколу [[w:TCP/IP|TCP/IP]] используется класс <tt>TCPSocket</tt> из библиотеки <tt>socket</tt>. Для того, чтобы наша задача была конкретней, мы заставим сервер (при помощи нашего клиента) выполнить следующие команды: <tt>ls</tt>, <tt>cd ..</tt>, <tt>ls</tt> и <tt>shutdown</tt>. Вывод результата выполнения этих команд мы будем осуществлять на экран, но пользователь не получит возможности изменять эту последовательность действий (кроме как исправив программу). Он увидит только результат. Логика здесь следующая: зачем заставлять пользователя вводить команды, если это может делать программа? Если же пользователю нужна другая последовательность команд, то пусть использует telnet или правит клиентскую часть под свои нужды.
}</code>
 
Все замечательно, но программа не работает. Не вся, конечно… Она выводит приглашение к диалогу и все, дальше виснет. Это связано с тем, что используется метод .read, который считывает весь поток целиком, пока не встретит символ EOF. Его, то наш сервер как раз и не передает. Не будем пока спешить и править сервер, а применим один нечестный прием: будем использовать не метод <code>.read</code>, а метод <code>.sysread( <u>n</u> )</code>. Почему прием нечестный? Да все потому, что метод <code>.sysread( n )</code> считывает <tt>n</tt>-первых сиволовсимволов из потока. Так как мы не знаем сколько нам надо считать символов, то мы зададим в качестве <tt>n</tt> очень большое число. Например, <tt>5000</tt>. Если символов в потоке меньше, чем <tt>5000</tt>, то <code>.sysread( n )</code> считает столько, сколько есть. Эту особенность мы и используем. Разве можно сказать, что такой прием честный?
 
<code>require 'socket'
Код стал выглядеть ужасней, зато стал более честным. Стоит отметить, что предложено три варианта обработки строки <tt>+OK</tt>. Правда, отличаются они лишь в деталях и функционально делают одно и то же. Давайте рассмотрим подробней решения, которые были реализованы в ходе исправления:
* <code>loop{ ... }</code>
Используя бесконечный цикл, мы получаем возможносьвозможность самостоятельно определять точку выхода из цикла. Это бывает полезно лишь на начальных стадиях реализации. Дальше лучше избавляться от бесконечного цикла и переходить сначала к циклам с предусловием, а потом (при возможности) к итераторам.
* <code>if <u>str[/^\+OK/]</u> then ... else ... end</code>
При помощи команды <code>str[/^\+OK/]</code> мы проверяем наличие строки <tt>+OK</tt> в переменной <tt>str</tt>. Если проверка прошла успешно, то происходит выход из бесконечного цикла. Если нет, то продолжается получение данных и вывод их на экран.
93

правки