Лекция по дисциплине Веб-дизайн на тему Клиент-серверное взаимодействие компьютеров и приложений


Лекция 1 Клиент-серверное взаимодействие компьютеров и приложений
План:
Технология работы с URL-адресами
2. Серверные приложения на основе сокетов
3. Клиентские приложения на основе сокетов
1. Технология работы с URL-адресами
Определение IP-адреса. Рассмотрим технологию определения доменного имени и числового IP-адреса при помощи методов класса InetAddress.
А. Проанализируйте структуру файла InetAddressDemo.java и обратите внимание на три возможных способа вызова методов класса InetAddress, при помощи которых осуществляется определение числового IP-адреса, а также его доменного имени.
Б. Создайте проект с именем InetAddressDemo согласно следующей методике:
Выбрать пункт меню File | New Project.
В панели Project Wizard Step 1 of 3 ввести в окно Name имя проекта и нажать на кнопку Finish.
Выбрать пункт меню File | New.
В панели Object Gallery выбрать вкладку General, выделить тип приложения Class и нажать на кнопку OK.
В панели Class Wizard ввести в окно Class Name имя класса, совпадающее с именем проекта, и нажать на кнопку OK.
Замените в проекте файл InetAddressDemo.java приводимым далее программным кодом и проведите тестирование проекта в среде JBuilder.
Файл InetAddressDemo.java
package inetaddressdemo;
import java.net.*;
//класс InetAddressDemoclass InetAddressDemo{
public static void main(String args[]) throws UnknownHostException {
//создание объекта класса InetAddress методом getLocalHost InetAddress Address = InetAddress.getLocalHost();
System.out.println(Address);
//создание объекта класса InetAddress методом getByName Address = InetAddress.getByName("127.0.0.1");
System.out.println(Address);
//создание объекта класса InetAddress методом getAllByName InetAddress ar[] = InetAddress.getAllByName("localhost");
for (int i=0; i<ar.length; i++)
System.out.println(ar[i]);
}
}
Определение компонентов URL-адреса. Рассмотрим методику определения компонентов URL-адресов при помощи методов класса URL.
А. Проанализируйте структуру файла MyURL.java и обратите внимание на методы класса URL, при помощи которых осуществляется определение имени протокола, номера порта, имени хоста и полного адреса URL.
Б. Создайте проект с именем MyURL согласно методике, изложенной на с. 65, заменив в проекте файл MyURL.java приводимым далее программным кодом. Протестируйте проект в среде JBuilder.
Файл MyURL.java
package myurl;
import java.net.*;
// класс MyURLclass MyURL {
public static void main(String args[]) throws MalformedURLException {
URL hp = new URL("https://www.eltech.ru/index.html");
// вывод имени протокола, порта, хоста, файла и URL
System.out.println("Протокол: " + hp.getProtocol());
System.out.println("Порт: " + hp.getPort());
System.out.println("Хост: " + hp.getHost());
System.out.println("Файл: " + hp.getFile());
System.out.println("URL: " + hp.toExternalForm());
}
}
Определение атрибутов удаленного ресурса. Рассмотрим методику просмотра свойств удаленного объекта перед его транспортировкой.
А. Проанализируйте структуру файла URLCon.java и обратите внимание на методы класса URLConnection, при помощи которых осуществляется определение даты, типа содержимого, срока хранения, времени последнего изменения и содержимого объекта URL.
Б. Создайте проект с именем URLCon согласно методике, изложенной на с. 65, заменив в проекте файл URLCon.java приводимым далее программным кодом. Протестируйте проект в среде JBuilder, используя в качестве объекта анализа приводимый далее файл Test.html.
Файл URLCon.java
package urlcon;
import java.net.*;
import java.io.*;
import java.util.Date;
// класс URLConclass URLCon{
public static void main(String args[]) throws Exception {
int c;
URL hp = new URL("https://127.0.0.1/Test.html");
URLConnection hpCon = hp.openConnection();
System.out.println("Дата: " + new Date(hpCon.getDate()));
System.out.println("Тип содержимого: " + hpCon.getContentType());
System.out.println("Срок хранения: " + hpCon.getExpiration());
System.out.println("Последнее изменение: " + new Date(hpCon.getLastModified()));
int len = hpCon.getContentLength();
System.out.println("Длина содержимого: " + len);
if (len > 0) {
System.out.println("=== Содержимое===");
InputStream input = hpCon.getInputStream();
int i = len;
while (((c = input.read()) != -1) && (--i > 0)) {
System.out.print((char) c);
}
input.close();
} else {
System.out.println("Нет содержимого");
}
}
}
Тестовый файл Test.html
<!-- Test.html -->
<html>
<head><title>Welcome to Our Store</title ></head >
<body>
<h1>Welcome to Our Store</h1>
<h1> HTML for Web-page. </h1>
</body >
</html>
2. Серверные приложения на основе сокетов
Методика создания сокетного соединения на сервере. Сокеты дают возможность одному процессу устанавливать соединение с другим процессом. Во время такого соединения оба процесса осуществляют обмен данными с помощью потоков, при этом используется протокол управления передачей данных TCP (Transmission Control Protocol).
Сокетное соединения на сервере реализуется выполнением следующих действий:
Создание объекта класса ServerSocket при помощи конструктора, аргументы которого задают допустимый номер порта и число клиентов, осуществляющих соединение с сервером.
ServerSocket s = new ServerSocket ( порт, длина очереди );
Обращение к методу accept класса ServerSocket для ожидания попыток соединения клиента с сервером
Socket connection = s.accept ();
Получение объектов потока вывода ObjectOutputStream и потока ввода ObjectInputStream, позволяющих клиенту взаимодействовать с сервером. Потоки вывода и ввода класса Socket создаются путем вызова методов getOutputStream и getInputStream
ObjectOutputStream output = new ObjectOutputStream( connection.getOutputStream() );
ObjectInputStream input = new ObjectInputStream( connection.getInputStream() );
Взаимодействие сервера и клиента через созданные потоки ввода и вывода.
Закрытие соединения путем вызова метода close класса Socket.
Реализация серверного приложения. Рассмотрим общую методику построения серверного приложения.
А. Проанализируйте структуру файла MyServer.java и обратите внимание на содержание методов main и jbInit, где создается необходимый интерфейс, и на структуру метода runServer, где реализуется сетевое взаимодействие на основе сокетного соединения.
Б. Создайте проект с именем MyServer согласно методике, изложенной на с. 65, заменив в проекте файл MyServer.java приводимым далее программным кодом. Протестируйте проект в среде JBuilder.
Файл MyServer.java
package myserver;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
//класс MyServerpublic class MyServer extends Frame {
private TextArea textArea1 = new TextArea();
private TextField textField1 = new TextField();
private ObjectOutputStream output;
private ObjectInputStream input;
public MyServer() {
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
MyServer mS = new MyServer();
mS.setTitle("Окно Сервера");
mS.setSize(350,250);
mS.setVisible(true);
mS.runServer();
}
private void jbInit() throws Exception {
textArea1.setBackground(Color.yellow);
textField1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
textField1_actionPerformed(e);
}
});
this.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(WindowEvent e) {
this_windowClosing(e);
}
});
this.add(textArea1, BorderLayout.CENTER);
this.add(textField1, BorderLayout.SOUTH);
}
void this_windowClosing(WindowEvent e) {
System.exit(0);
}
void textField1_actionPerformed(ActionEvent e) {
sendData( e.getActionCommand() );
}
public void runServer() {
ServerSocket server;
Socket connection;
int counter = 1;
try {
// Шаг 1 : создание объекта ServerSocket.
server = new ServerSocket( 2000, 100 );
while ( true ) {
// Шаг 2 : ожидание соединения.
textArea1.setText( "Ожидание соединения\n" );
connection = server.accept();
textArea1.append( "Соединение " + counter +
" получено от: " +
connection.getInetAddress().getHostName() );
// Шаг 3 : создание потоков ввода и вывода.
output = new ObjectOutputStream(
connection.getOutputStream() );
output.flush();
input = new ObjectInputStream(
connection.getInputStream() );
textArea1.append( "\nСозданы потоки ввода и вывода\n" );
// Шаг 4 : работа с соединением.
String msg =
"SERVER ==> Соединение прошло успешно ";
output.writeObject( msg );
output.flush();
textField1.setEnabled( true );
do {
try {
msg = (String) input.readObject();
textArea1.append( "\n" + msg );
textArea1.setCaretPosition(
textArea1.getText().length() );
}
catch ( ClassNotFoundException cnfex ) {
textArea1.append(
"\nПолучен неизвестный тип объекта" );
}
} while ( !msg.equals( "CLIENT ==> ЗАКОНЧИТЬ" ) );
// Шаг 5 : закрытие соединения.
textArea1.append( "\nКлиент закончил соединение" );
textField1.setEnabled( false );
output.close();
input.close();
connection.close();
++counter;
}
}
catch ( EOFException eof ) {
System.out.println( "Клиент закончил соединение" );
}
catch ( IOException io ) {
io.printStackTrace();
}
}
private void sendData( String s ) {
try {
output.writeObject( "SERVER ==> " + s );
output.flush();
textArea1.append( "\nSERVER ==>" + s );
}
catch ( IOException cnfex ) {
textArea1.append(
"\nОшибка при выводе" );
}
}
}
3.Клиентские приложения на основе сокетов
Методика создания сокетного соединения клиента. Сокетное соединение на стороне клиента реализуется путем выполнения следующих действий:
Создание объекта класса Socket при помощи конструктора класса
Socket connection = new Socket ( адрес, порт );
Аргументы конструктора задают используемый адрес и номер порта
сервера.
Получение объектов потока вывода ObjectOutputStream и потока ввода ObjectInputStream, позволяющих клиенту взаимодействовать с сервером. Для создания потоков используются методы getOutputStream и getInputStream класса Socket
ObjectOutputStream output = new ObjectOutputStream(
connection.getOutputStream() );
ObjectInputStream input = new ObjectInputStream(
connection.getInputStream() );
Взаимодействие сервера и клиента через созданные потоки вывода и ввода.
Закрытие соединения путем вызова метода close класса Socket.
Реализация клиентского приложения. Рассмотрим общую методику построения клиентского приложения.
А. Проанализируйте структуру файла MyClient.java и обратите внимание на содержание методов main и jbInit, где создается необходимый интерфейс, и на структуру метода runClient, где реализуется сетевое взаимодействие на основе сокетного соединения.
Б. Создайте проект с именем MyClient согласно методике, изложенной на с. 65, заменив в проекте файл MyClient.java приводимым далее программным кодом. Протестируйте проект в среде JBuilder.
Файл MyClient.java
package myclient;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
// класс MyClientpublic class MyClient extends Frame {
private TextArea textArea1 = new TextArea();
private TextField textField1 = new TextField();
private ObjectOutputStream output;
private ObjectInputStream input;
private String msg = "";
public MyClient() {
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
MyClient mC = new MyClient();
mC.setTitle("Окно Клиента");
mC.setSize(300,300);
mC.setVisible(true);
mC.runClient();
}
private void jbInit() throws Exception {
textArea1.setBackground(Color.cyan);
textField1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
textField1_actionPerformed(e);
}
});
this.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(WindowEvent e) {
this_windowClosing(e);
}
});
this.add(textArea1, BorderLayout.CENTER);
this.add(textField1, BorderLayout.SOUTH);
}
void textField1_actionPerformed(ActionEvent e) {
sendData( e.getActionCommand() );
}
void this_windowClosing(WindowEvent e) {
System.exit(0);
}
public void runClient() {
Socket client;
try {
// Шаг 1 : создание сокета для соединения.
textArea1.setText( "Попытка соединения\n" );
client = new Socket( InetAddress.getByName( "127.0.0.1" ), 2000 );
textArea1.append( "Соединен с: " +
client.getInetAddress().getHostName() );
// Шаг 2 : создание потоков ввода и вывода.
output = new ObjectOutputStream( client.getOutputStream() );
output.flush();
input = new ObjectInputStream( client.getInputStream() );
textArea1.append( "\nСозданы потоки ввода и вывода \n" );
textArea1.append( "\nДля прекращения связи ввести: ЗАКОНЧИТЬ \n" );
// Шаг 3 : работа с соединением.
textField1.setEnabled( true );
do {
try {
msg = (String) input.readObject();
textArea1.append( "\n" + msg );
textArea1.setCaretPosition(
textArea1.getText().length() );
}
catch ( ClassNotFoundException cnfex ) {
textArea1.append( "\nПолучен неизвестный тип объекта" );
}
} while ( !msg.equals( "SERVER ==> ЗАКОНЧИТЬ" ) );
// Шаг 4 : закрытие соединения.
textArea1.append( "\nЗакрытие соединения.\n" );
output.close();
input.close();
client.close();
}
catch ( EOFException eof ) {
System.out.println( "Сервер закончил соединение" );
}
catch ( IOException e ) {
e.printStackTrace();
}
}
private void sendData( String s ) {
try {
msg = s;
output.writeObject( "CLIENT ==> " + s );
output.flush();
textArea1.append( "\nCLIENT ==> " + s );
}
catch ( IOException cnfex ) {
textArea1.append( "\nОшибка вывода объекта" );
}
}
}