| |
акрываем входной и выходной потоки
is.close();
os.close();
// Закрываем сокет сервера
s.close();
// Закрываем соединение
ss.close();
}
catch(Exception ioe)
{
System.out.println(ioe.toString());
}
try
{
System.out.println(
"Press to terminate application...");
System.in.read(bKbdInput);
}
catch(Exception ioe)
{
System.out.println(ioe.toString());
}
}
}
Описание исходного текста серверного приложения SocketServ
В методе main, получающем управление сразу после запуска приложения, мы
определили несколько переменных.
Массив bKbdInput размером 256 байт предназначен для хранения строк,
введенных при помощи клавиатуры.
В переменную ss класса ServerSocket будет записана ссылка на объект,
предназначенный для установления канала связи через потоковый сокет (но не
ссылка на сам сокет):
ServerSocket ss;
Ссылка на сокет, с использованием которого будет происходить передача данных,
хранится в переменной с именем s класса Socket:
Socket s;
Кроме того, мы определили переменные is и os, соответственно, классов
InputStream и OutputStream:
InputStream is;
OutputStream os;
В эти переменные будут записаны ссылки на входной и выходной поток данных,
которые связаны с сокетом.
После отображения на консоли строки названия приложения, метод main создает
объект класса ServerSocket, указывая конструктору номер порта 9999:
ss = new ServerSocket(9999);
Конструктор возвращает ссылку на объект, с использованием которого можно
установить канал передачи данных с клиентом.
Канал устанавливается методом accept:
s = ss.accept();
Этот метод переводит приложение в состояние ожидания до тех пор, пока не
будет установлен канал передачи данных.
Метод accept в случае успешного создания канала передачи данных возвращает
ссылку на сокет, с применением которого нужно принимать и передавать данные.
На следующем этапе сервер создает входной и выходной потоки, вызывая для
этого методы getInputStream и getOutputStream, соответственно:
is = s.getInputStream();
os = s.getOutputStream();
Далее приложение подготавливает буфер buf для приема данных и определяет
переменную length, в которую будет записываться размер принятого блока данных:
byte buf[] = new byte[512];
int lenght;
Теперь все готово для запуска цикла приема и обработки строк от клиентского
приложения.
Для чтения строки мы вызываем метод read применительно ко входному потоку:
lenght = is.read(buf);
Этот метод возвращает управление только после того, как все данные будут
прочитаны, блокируя приложение на время своей работы. Если такая блокировка
нежелательна, вам следует выполнять обмен данными через сокет в отдельной
задаче.
Метод read возвращает размер принятого блока данных или -1, если поток
исчерпан. Мы воспользовались этим обстоятельством для завершения цикла приема
данных:
if(lenght == -1)
break;
После завершения приема блока данных мы преобразуем массив в текстовую
строку str класса String, удаляя из нее символ перевода строки, и отображаем
результат на консоли сервера:
System.out.println("> " + str);
Затем полученная строка отправляется обратно клиентскому приложению, для
чего вызывается метод write:
os.write(buf, 0, lenght);
Методу write передается ссылка на массив, смещение начала данных в этом
массиве, равное нулю, и размер принятого блока данных.
Для исключения задержек в передаче данных из-за накопления данных в буфере
(при использовании буферизованных потоков) необходимо принудительно сбрасывать
содержимое буфреа метдом flush:
os.flush();
И хотя в нашем случае мы не пользуемся буферизованными потоками, мы включили
вызов этого метода для примера.
Теперь о завершающих действиях после прерывания цикла получения, отображения
и передачи строк.
Наше приложение явням образом закрывает входной и выходной потоки данных,
сокет, а также объект класса ServerSocket, с использованием которого был создан
канал передачи данных:
is.close();
os.close();
s.close();
ss.close();
Исходный текст клиентского приложения SocketClient
Исходный текст клиентского приложения SocketClient приведен в листинге 3.6.
Листинг 3.6. Файл SocketClient\SocketClient.java
// =========================================================
// Использование потоковых сокетов.
// Приложение клиента
//
// (C) Фролов А.В, 1997
//
// E-mail: [email protected]
// WWW: http://www.glasnet.ru/~frolov
// или
// http://www.dials.ccas.ru/frolov
// ==============
|
|