Работа в WWW
Среди программного обеспечения Internet большое распространение получила информационная система WWW (World Wide Web), основанная на прикладном протоколе HTTP (Hypertext Transfer Protocol). В ней используется расширенная адресация, называемая URL (Uniform Resource Locator). Эта адресация имеет такие схемы:
protocol://authority@host:port/path/file#ref
protocol://authority@host:port/path/file/extra_path?info
Здесь необязательная часть authority — это пара имя:пароль для доступа к хосту, host — это IP-адрес или доменное имя хоста. Например:
http://www.bhv.ru/
http://132.192.5.10:8080/public/some.html
ftp://guest:password@lenta.ru/users/local/pub
ffle:///C:/text/html/index.htm
Если какой-то элемент URL отсутствует, то берется стандартное значение. Например, в первом примере номер порта port равен 80, а имя файла path — какой-то головной файл, определяемый хостом, чаще всего это файл с именем index.html. В третьем примере номер порта равен 21. В последнем примере в форме URL просто записано имя файла index.htm, расположенного на разделе С: жесткого диска той же самой машины.
В Java для работы с URL есть класс URL пакета java.net. Объект этого класса создается одним из шести конструкторов. В основном конструкторе
URL(String url)
задается расширенный адрес url в виде строки. Кроме методов доступа getxxxo, позволяющих получить элементы URL, в этом классе есть два интересных метода:
openConnection ()
— определяет связь с URL и возвращает объект класса
URLConnection;
openStream()
— устанавливает связь с URL и открывает входной поток в виде возвращаемого объекта класса inputstream.
Листинг 19.1 показывает, как легко можно получить файл из Internet, пользуясь методом openStream().
Листинг 19.1.
Получение Web-страницы
import java.net.*;
import j ava.io.*;
class SimpleURL{
public static void main(String[] args){
try{
http://www.bhv.ru/
");
BufferedReader br = new BufferedReader(
new InputStreamReader(bhv.openStream()));
String line;
while ((line = br.readLine()) != null)
System.out.println(line);
br.close();
}catch(MalformedURLException me){
System.err.println("Unknown host: " + me);
System.exit(0);
}catch(IOException ioe){
System.err.println("Input error: " + ioe);
}
}
}
Если вам надо не только получить информацию с хоста, но и узнать ее тип: текст, гипертекст, архивный файл, изображение, звук, или выяснить длину файла, или передать информацию на хост, то необходимо сначала методом openConnection () создать объект класса URLConnection или его подкласса
HttpURLConnection.
После создания объекта соединение еще не установлено, и можно задать параметры связи. Это делается следующими методами:
setDoOutput (boolean out)
— если аргумент out равен true, то передача пойдет от клиента на хост; значение по умолчанию false;
setDoinput (boolean in)
— если аргумент in равен true, то передача пойдет с хоста к клиенту; значение по умолчанию true, но если уже выполнено setDoOutput(true), то значение по умолчанию равно false;
setUseCaches (boolean cache)
— если аргумент cache равен false, то передача пойдет без кэширования, если true, то принимается режим по умолчанию;
setDefaultUseCaches(boolean default)
— если аргумент default равен true, то принимается режим кэширования, предусмотренный протоколом;
setRequestProperty(String name, String value) —
добавляет параметр name со значением value к заголовку посылаемого сообщения.
После задания параметров нужно установить соединение методом connect (). После соединения задание параметров уже невозможно. Следует учесть, что некоторые методы доступа getxxxo, которым надо получить свои значения с хоста, автоматически устанавливают соединение, и обращение к методу connect () становится излишним.
Web-сервер возвращает информацию, запрошенную клиентом, вместе с заголовком, сведения из которого можно получить методами getxxxo, например:
getcontentType ()
— возвращает строку типа string, показывающую тип пересланной информации, например, "text/html", или null, если сервер его не указал;
getcontentLength ()
— возвращает длину полученной информации в байтах или — 1, если сервер ее не указал;
getcontent ()
— возвращает полученную информацию в виде объекта типа Object;
getContentEncoding ()
— возвращает строку типа string с кодировкой полученной информации, или null, если сервер ее не указал.
Два метода возвращают потоки ввода/вывода, созданные для данного соединения:
getlnputStream()
— возвращает входной поток типа InputStream;
getOutputStream()
— возвращает выходной поток типа OutputStream.
Прочие методы, а их около двадцати, возвращают различные параметры соединения.
Обращение к методу bhv.openstreamo, записанное в листинге 19.1, — это, на самом деле, сокращение записи
bhv.openConnection().getlnputStream()
В листинге 19.2 показано, как переслать строку текста по адресу URL.
Web-сервер, который получает эту строку, не знает, что делать с полученной информацией. Занести ее в файл? Но с каким именем, и есть ли у него право создавать файлы? Переслать на другую машину? Но куда?
Выход был найден в системе CGI (Common Gateway Interface), которая вкратце действует следующим образом. При посылке сообщения мы указываем URL исполнимого файла некоторой программы, размещенной на машине-сервере. Получив сообщение, Web-сервер запускает эту программу и передает сообщение на ее стандартный ввод. Вот программа-то и знает, что делать с полученным сообщением. Она обрабатывает сообщение и выводит результат обработки на свой стандартный вывод. Web-сервер подключается к стандартному выводу, принимает результат и отправляет его обратно клиенту.
CGI-программу можно написать на любом языке: С, C++, Pascal, Perl, PHP, лишь бы у нее был стандартный ввод и стандартный вывод. Можно написать ее и на Java, но в технологии Java есть более изящное решение этой задачи с помощью сервлетов (servlets). CGI-программы обычно лежат на сервере в каталоге cgi-bin.
Листинг 19.2.
Посылка строки по адресу URL
import java.net.*;
import java.io.*;
class PostURL{
public static void main(String[] args){
String req = " This text is posting to URL";
try{
// Указываем URL нужной CGI-программы
URL url = new URL("
http://www.bhv.ru/cgi-bin/some.pl
");
// Создаем объект uc
URLConnection uc = url.openConnection();
// Собираемся отправлять
uc.setDoOutput(true);
// и получать сообщения
uc.setDoInput(true);
// без кэширования
uc.setUseCaches(false);
// Задаем тип
uc.setRequestProperty("content-type",
"application/octet-stream");
// и длину сообщения
uc.setRequestProperty("content-length", "" + req.length());
// Устанавливаем соединение
uc.connect();
// Открываем выходной поток
DataOutputStream dos = new DataOutputStream( uc.getOutputStreamO);
// и выводим в него сообщение, посылая его на адрес
URL dos.writeBytes(req);
// Закрываем выходной поток
dos.close();
// Открываем входной поток для ответа сервера
BufferedReader br = new BufferedReader(new InputStreamReader(
uc.getlnputStream() )) ;
String res = null;
// Читаем ответ сервера и выводим его на консоль
while ((res = br.readLine()) != null)
System.out.println(res);
br.close () ;
}catch(MalformedURLException me){
System.err.println(me);
}catch(UnknownHostException he){
System.err.println(he);
}catch(UnknownServiceException se){
System.err.println(se);
}catch(IOException ioe){
System.err.println(ioe);
}
}
}