КАТЕГОРИИ: Архитектура-(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-серверу
В этой таблице указаны стандартные заголовки. Для анализа данных, которые пересылаются при отправке параметров от клиента, удобно пользоваться программой 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 указывается количество символов, составляющих розт-запрос. Само тело запроса является последним набором данных, передаваемых от клиента к серверу. Здесь так много внимания было уделено анализу содержимого заголовков в связи с тем, что их корректная обработка является залогом надежной работы всего сервера.
Обзор структуры сервера Создаваемая программа будет состоять из нескольких функциональных частей:
Реализация 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; Просмотров: 427; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |