Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Замечание. Обратите внимание, что отправка HTTP-заголовков клиенту осуществляется в соответствии с правилами, изложенными в гл




Обратите внимание, что отправка HTTP-заголовков клиенту осуществляется в соответствии с правилами, изложенными в гл. 9, в разделе, посвященном прямому выводу информации.

Запустив созданное приложение, браузер, а затем, указав в адресной строке последнего localhost, на экране можно увидеть искомую информацию (рис. 15.1).

Рис. 15.1. Результат работы созданного вспомогательного сервера Описание полей посылаемого браузером запроса приведено в табл. 15.1.

Таблица 15.1. Описание данных, отправленных клиентом Web-серверу

Заголовок поля Описание
'GET/ Содержит название метода запроса, которым воспользовался клиент. После значка / содержится дополнительная информация об адресе запрашиваемой Web-страницы, либо название команды, предусмотренной сервером

 

НТТР/1.1 Содержит название и версию используемого протокола
Accept: */* Содержит тип MIME-данных, которые готов принять браузер в качестве ответа сервера
Accept-Language: ru Содержит основной язык браузера
Accept-Encoding Содержит поддерживаемые форматы упаковки файлов
User-Agent Содержит тип агента пользователя (браузера)
Host Содержит адрес сайта
Connection Содержит тип соединения, которое поддерживает клиент. Этот заголовок, как правило, используется для указания того, что браузер поддерживает долгоживущие соединения

В этой таблице указаны стандартные заголовки. Для анализа данных, которые пересылаются при отправке параметров от клиента, удобно пользоваться программой HTTPDemo, поставляемой вместе в Delphi в качестве примера. Она позволяет передавать GET- и розт-запросы серверу и отображать его ответы. Также можно создать простейшую Web-страницу с формами для отправки данных, с помощью которых производится анализ содержимого клиентских HTTP-заголовков. Так и поступим (листинг 15.3).

Листинг 15.3. Исходный код вспомогательной Web-страницы

<HTML>

<P><FORM method=POST action="http://localhost">

<INPUT type=text name="mymessage">

<BR>

<INPUT type=Submit name="Submut" Уа1ие="0тправить">

</FORM>

<PXFORM method=GET action="http://localhost">

<INPUT type=text name="mymessage">

<INPUT type=Submit name="Submut" Уа1ие="0тправить">

</FORM>

</HTML>

Если текстовые поля заполнить значением "Сообщение", а затем последовательно воспользоваться обеими кнопками отправки, то отправляемые клиентом заголовки примут вид, приведенный в листингах 15.4 и 15.5.

Листинг 15.4. HTTP-заголовки, формируемые при передаче данных от клиента методом POST

POST / HTTP/1.1 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, */* Accept-Language: ru Content-Type: application/x-www-form-urlencoded Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0) Host: localhost Content-Length: 72 Connection: Keep-Alive mymessage=%Dl%EE%EE%El%F9%E5%ED%E8%E5

&Submut=%CE%F2%EF%FO%EO%E2%E8%F2%FC

Листинг 15.5. HTTP-заголовки, формируемые при передаче данных от клиента методом GET

GET /?mymessage=%Dl%EE%EE%El%F9%E5%ED%E8%E5&Submut=

%CE%F2%EF%FO%EO%E2%E8%F2%FC HTTP/1.1 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, */* Accept-Language: ru Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0) Host: localhost Connection: Keep-Alive

Приведенные листинги отличаются от текста на Web-странице, изображенной на рис. 15.1. Листинг 15.5 содержит дополнительные сведения СЕТ-запроса, указанные после вопросительного знака. Если бы клиент указал дополнительный адрес запрашиваемого документа, то путь к нему разместился бы между символом / и вопросительным знаком. Правила кодировки информации при передаче через Интернет и в СЕТ-запросах в частности, подробно изложены в гл. 9, поэтому здесь мы не будем останавливаться на них.

В методе POST, после указания названия этого метода, как и в СЕТ-случае, присутствует символ /, после которого должен следовать адрес запрашиваемого документа, либо команда серверу. Поскольку в Web-странице в поле action формы был указан только сервер, то данный параметр опущен. Кроме прочих заголовков, здесь в параметре Content-Length указывается количество символов, составляющих розт-запрос. Само тело запроса является последним набором данных, передаваемых от клиента к серверу.

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

 

Обзор структуры сервера

Создаваемая программа будет состоять из нескольких функциональных частей:

  • Процедура разбора данных и определение алгоритма дальнейших действий. Здесь из всех сведений, полученных от клиента, будут выделены собственно данные запроса, а также, в случае статичности требуемого результата, сформирован ответ. Кроме того, если в запросе пользователь прислал новое сообщение, которое должно быть добавлено к уже полученным, то его текст будет преобразован к XML-представлению с целью дальнейшей обработки.
  • Процедура отправки данных клиенту. В ней будет обеспечена отправка предварительно сформированного HTML-документа вместе с требуемыми, согласно протокола HTTP, заголовками.
  • Процедура добавления нового сообщения к списку таковых. Здесь XML-данные нового послания будут переведены в формат HTML и, затем, приобщены ко всем имеющимся сообщениям.
  • Процедура приведения банка всех посланий, хранящихся в HTML-формате, к виду, необходимому для корректного отображения. В ней, к телу сформированного документа добавятся стилевые параметры и стандартные для Web-страниц элементы.
  • Использование внутреннего XML-представления получаемых от клиента сообщений обеспечивает удобство передачи данных между процедурами и гибкость настройки последующего форматирования документа.

Реализация Web-сервера

Для реализации сервера будем использовать обычное визуальное приложение. Применение форм обусловлено необходимостью работы приложения в состоянии ожидания новых подключений. Обычное невизуальное (консольное) приложение после завершения всех операций, предусмотренных программистом, заканчивает свою работу, в то время, как приложение с формой будет активно до тех пор, пока от графической системы Windows не будет получено сообщение о необходимости прекращения работы. До этого, программа находится в состоянии ожидания новых сообщений. Для того чтобы заставить консольное приложение работать до тех пор, пока не будет явного указания к закрытию, нужно реализовывать специальный алгоритм, базирующийся на Windows API-функциях. Здесь мы этим заниматься не будем.

На форму нового приложения следует поместить всего два компонента — serverSocket и NMURL. После того необходимо установить следующие свойства первого:

Name: MainSocket, Port: 80, Service: Http, Active: True.

Второй следует просто переименовать в TransiateMess.

Далее, путем определения новых переменных, которые будут использоваться в программе, модернизируется секция private класса тгопгй (листинг 15.6).

Листинг 15.6. Секция private определения класса TForml

private

tmp, HTMLmessages: string;

users: tstrings;

refresh: booi;

Переменная tmp предназначена для обмена данными о содержимом ответа пользователю между процедурами. В HTMLmessages будет храниться банк посланий от клиентов, users используется в качестве массива, содержащего строки вида

IРАдресКлиента=ИмяПользователя

для идентификации клиентов. Обратите внимание, что объекты типа TstringList снабжены большим набором методов, осуществляющих управление данными такого вида.

Поскольку наш сервер должен посылать часть Web-страниц со специальным HTTP-заголовком, который указывает браузеру на необходимость обновления их содержимого через определенный интервал времени (см. в гл. 9 Pull-метод), то режим отправки ответа пользователю и будет определяться состоянием переменной refresh.

В начале работы программы необходимо создать объект users и присвоить переменной refresh значение по умолчанию (листинг 15.7).

Листинг 15.7. Начальные действия в программе

procedure TForml.FormCreate(Sender: TObject); begin

users:=TstringList.Create; refresh:=false; end;

Вслед за совершением начальных операций программа готова к приему данных (листинг 15.8).

Листинг 15.8. Процедура чтения данных от клиента

procedure TForml.MainSocketClientRead(Sender: TObject;

Socket: TCustomWinSocket); var direction, content:string; begin

content:=(Socket.ReceiveText);

// Здесь все содержимое HTTP-запроса передано в переменную content if pos('GET',content)=1 then

// Здесь происходит определения метода запроса (передачи данных // на сервер). В дальнейшем идет обработка метода POST и GET. direction:=copy(content, (pos('GET1,content)+5),

(pos('HTTP',content)-!)-(pos('GET',content)+5))

else

direction:=copy(content, (pos('POST1,content)+6),

(pos('HTTP',content)-1)-(pos('POST',content)+6)); // В этом фрагменте кода было обеспечено извлечение данных // о запрашиваемом динамически формируемом документе.

if direction = 'registration1 then

// Здесь происходит передача страницы входа на сервер в переменную tmp.

begin

tmp:='<HTML>'+

'<TITLE> Вход на сервер </TITLE>'+

'<Н2> Вход на сервер </Н2>'+

'<DIV style="border-style: double; border-color: silver;'+

'width: 400px; height: 100px;'+ 'ALIGN: center; background-color: ttFODBF2">'+ '<FORM method=POST action="http://localhost/framesetl">'+ '<Р>Введите имя, под которым Вы хотите войти в систему.'+ '<INPUT type=text name="username">'+ '<P><INPUT type=Submit name="Submit" value="BoUTH">'+ '</FORM>'+ '</DIV>'+ '</HTML>';

end;

if direction = 'framesetl' then

// Генерация фреймсодержащей страницы — главного окна чата. begin

tmp:=content; content:=Copy(tmp,Pos{'username=',content)+9,

(Pos('&Submit=',content)-Pos('username=',content)-9)); // Выделение из полученных от клиента данных подстроки, содержащей имя // пользователя.

TranslateMess.InputString:=content; content:=TranslateMess.Decode; // Раскодировка веделенной информации (приведение к стандартному виду).

if users.lndexOfName(socket.RemoteAddress) = -1 then // Проверка — является ли клиент новым, или он уже находится в чате?

begin

// Обработка ситуации, когда клиент является новым. Формируется // фреймсодержащая страница.

users.Add(socket.RemoteAddress+'='+content); tmp:='<HTML>'+

'<TITLE> Наш чат </TITLE>'+

'<FRAMESET rows="*,150">'+

1<FRAME src="http://localhost/messages" name="mess">'+ '<FRAME src="http://localhost/addingmessages"'+ 'name="adding">'+ '</FRAMESET>'+ '</HTML>';

end

else

// Обработка ситуации двойного входа в чат. begin

tmp:='<HTML>'+

'<TITLE> Ошибка регистрации </TITLE>'+

'<Н4> Уважаемый пользователь! Ваш IP-адрес уже' +

'зарегистрирован в Чате.'-t-1<BR>Haui чат не позволяет одному пользователю'+

'обмениваться сообщениями ' + 'под несколькими псевдонимами</Н4>'+ '</HTML>'; end; end;

if direction = 'addingmessages' then

// Здесь генерируется страничка с формой для добавления нового сообщения. begin

tmp:='<HTML>'+

'<FORM Method=Post Action="http://localhost/messages" target="mess">'+ '<INPUT type=text name="message">'+

'<INPUT type="Submit" name="Submit" Уа1ие="Послать сообщение">'+ '</FORM>'+ '</HTML>';

end;

if direction = 'messages' then

// Блок, отображающий список всех сообщений, а также добавление новых. begin content:=Copy(content,Pos('message=',content)+8,

(Pos('Submit=',content)-1-(Pos('message=',content)+ 8})); // Выделение нового послания.

TranslateMess.InputString:=content;

content:=TranslateMess.Decode;

if (length(HtmiMessages) = 0) and (length(content)=0) then

tmp:='<Р>Сообщений пока нет'

// Проверка — есть ли хоть одно послание или добавляется новое.

else

begin

refresh:=true;

// Установка режима передачи HTTP-заголовка для обновления страницы, tmp:='<message author="'+users.Values[socket.RemoteAddress] +' "><mbody>'+content+'</mbody></message>';

// Формирование XML-представления нового послания.

Xmltohtmlmessages(tmp);

// Добавление нового послания к переменной, содержащей предыдущие.

tmp:=setskin;

// Добавление стандартных HTML-элементов.

end;

end;

end;

После того как сообщение от клиента получено, оно, с целью его добавления к списку всех сообщений, помещается в специальном виде в параметр вызова процедуры Xmltohtmlmessages, реализация которой приведена в листинге 15.9.

Листинг 15.9. Реализация процедуры Xmltohtmlmessages

procedure TForml.Xmltohtmlmessages(addingmess:string); begin

if length(copy(addingmess,(pos('<mbody>',addingmess)+7},

(pos('</mbody>',addingmess)-(pos('<mbody>',addingmess)+7))))>0 then begin

HtmlMessages:=

copy(addingmess, (pos('<mbody>',addingmess)+7), (pos('</mbody>',addingmess)-

(pos('<mbody>',addingmess)+7)))+'<BR>'+HtmlMessages; // Здесь происходит выделение из параметра вызова процедуры // непосредственно сообщения и информации об авторе и добавление этих // данных в переменную HtmlMessages, содержащую все сообщения в формате // HTML.

HtmlMessages:='<SPAN class="name">'+ copy(addingmess,(pos('author=',addingmess)+8), (pos('">',addingmess)-(pos('author=',addingmess)+8)))+ ': <SPAN class="mess">'+HtmlMessages; end; end;

Далее, формируя Web-страницу, следует добавить в отправляемый HTML-код информацию о стиле и теги начала и конца документа. Эта операция реализована в процедуре setskin, код которой приведен в листинге 15.10.

Листинг 15.10. Добавление стилевых параметров в формируемую Web-страницу

function TForml.setskin:string; begin

if length(HtmlMessages) = 0 then HtmlMessages:='<Р>Сообщений пока нет';

Result:='<HTML>'+

'<STYLE type="text/ess">'#13#10+

'.name {color:red; font-weight:bold; font-style:italic; font-size: 12pt; }'#13#10+

'.mess {color:black; font-size:14pt;}'#13#10+

'</STYLE>'ttl3#10+Htmlmessages+'</HTML>';

end;

После того как Web-страница готова, ее можно отправлять клиенту. К телу самой страницы, т. е. HTML-коду, следует добавить HTTP-заголовки, и передать эту информацию через сокетное соединение, как показано в листинге 15.11.

Листинг 15.11. Процедура отправки HTTP-сообщения клиенту

procedure TForml.MainSocketClientWrite(Sender: TObject;

Socket: TCustomWinSocket);

begin

Socket.SendTextCHTTP/1.1 200 Ok'#13#10); if refresh = true then

// Поскольку данная процедура применяется при отправке всех страниц, то // нужно проверять — необходимо ли указывать браузеру обновлять страницу // через, например, 30 секунд. begin

refresh:=false;

Socket.SendText('Refresh:30; URL="http://localhost/messages"');

end;

Socket.SendText('Connection: close'#13#10);

// Данный заголовок устанавливает режим, когда после получения страницы // браузер прекращает соединение с сервером.

// Сочетание #13#10 является служебным символом, означающим перевод строки. // Его использование обусловлено необходимостью отделения HTTP-заголовков. Socket.SendText('Content-Type: text/html'#13#10); Socket.SendText('Ч13#10); Socket.SendText(tmp+#13#10);

Socket.Close;

Socket.Free;

end;

Итак, после того, как в браузере, предварительно запустив созданную программу, набрать строку http://localhost/registration, будет загружена страница входа в чат, представленная на рис. 15.2.

После ввода имени пользователя и нажатия кнопки Войти в браузер загрузится фреймсодержащая страница. После этого можно отправлять сообщения. Главное окно работы созданного сервера обмена сообщениями представлено на рис. 15.3.

Рис. 15.2. Страница регистрации на сервере

Рис. 15.3. Результат работы Web-сервера

Итак, мы создали сервер, основной задачей которого является предоставление возможности пользователям обмениваться сообщениями. Если на компьютере уже установлен Web-сервер, то программу можно использовать, указав номер сетевого порта, отличный от порта Web-сервера (например, 800), чтобы не возникало конфликтной ситуации. В этом случае, все ссылки нужно поменять, добавив после адреса, через двоеточие, номер порта. Например, http://localhost/registration переходит в http://localhost /registration: 800.

ПРИЛОЖЕНИЕ 1




Поделиться с друзьями:


Дата добавления: 2014-12-29; Просмотров: 403; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.061 сек.