Московский государственный университет имени М.В.Ломоносова
Опубликован: 01.11.2004 | Доступ: свободный | Студентов: 11271 / 455 | Оценка: 4.12 / 4.01 | Длительность: 19:20:00
ISBN: 978-5-9556-0077-9
Специальности: Программист
Лекция 28:

Серверные приложения

< Лекция 27 || Лекция 28: 1234
Аннотация: В лекции описывается взаимодействие приложений по протоколу TCP/IP, рассматриваются основы построения серверных приложений. Дается обзор классов, используемых для реализации серверного приложения на языке С++ в среде проектирования Visual Studio.NET и на языке Object Pascal в среде проектирования Borland Developer Studio (Delphi for Win32). Изучается создание WEB-форм в VisualStudio .NET.

Взаимодействие по протоколу TCP/IP

Протокол TCP/IP (Transmission Control Protocol/Internet Protocol) предназначен для установления соединения между двумя компьютерами в сети, обычно называемыми клиентом и сервером. Протокол TCP/IP определяет IP-адрес и номер порта.

IP-адрес задает имя компьютера в сети. IP-адрес указывается или как числовой идентификатор компьютера, или, при использовании сервера DNS, - как символьный псевдоним числового идентификатора.

Локальный компьютер всегда адресуется как 127.0.0.1 или localhost.

При работе в Интернете все используемые IP-адреса уникальны. Поэтому для задания своему ПК некоторого IP-адреса следует получить этот адрес у провайдера.

При работе только в локальной сети предприятия можно самостоятельно установить различные IP-адреса для каждого ПК. Например: 192.168.0.2; 192.168.0.3; 192.168.0.4 и т.д.

Номер порта - это значение, однозначно идентифицирующее некоторый логический порт приложения, через который можно получать и посылать данные.

Создание серверных приложений на С++ в среде проектирования VisualStudio .NET

CGI и ISAPI приложения

Данные, отображаемые web-браузером, представляют собой HTML-страницу.

По HTTP-запросу web-браузер посылает на web-сервер информацию, содержащую URL-адрес документа, тип запроса и значения параметров. URL-адрес может указывать как простую HTML-страницу и приложение, выполняемое на web-сервере. Такое приложение иногда называется серверным приложением.

К серверным приложениям относятся CGI-приложения и ISAPI-приложения.

В отличии от CGI-приложений, выполняемых в отдельном процессе, ISAPI-приложения реализуются как DLL-библиотеки.

Результатом выполнения CGI или ISAPI-приложения чаще всего является динамически сформированная HTML-страница.

HTTP-запросы

НТТР-запрос формируется в соответствии с протоколом HTTP (HyperText Transfer Protocol). В HTTP-запросе указывается GET- или POST-метод передачи данных. При вводе URL-адреса в поле адреса web-браузера или выполнении формы (пользователь щелкнул по кнопке типа SUBMIT) формируется HTTP-запрос. Если форма содержала данные, то они будут добавлены в конец строки с URL-адресом (при использовании метода GET). Соответственно, такой способ накладывает ограничение на размер передаваемых параметров. Если при выполнении формы атрибут METOD установлен равным POST, то используется POST-метод, при котором сначала на сервер посылается строка POST-запроса и HTTP-заголовки запроса, а затем пустая строка и строка, содержащая передаваемые параметры.

ISAPI-приложение может использоваться как для формирования динамической HTML-страницы, так и для обработки параметров, получаемых от формы.

В строке адреса web-браузера может быть указан только непосредственно URL-адрес выполняемого серверного приложения. В этом случае для обработки такого запроса используется команда, определяемая макросом DEFAULT_PARSE_COMMAND.

Если после URL-адреса за вопросительным знаком следует идентификатор команды, то для обработки данного HTTP-запроса следует использовать функцию, сопоставленную данной команде макросом ON_PARSE_COMMAND.

Например, для обработки строки

http://LOCALHOST/MyISAPI_1.dll?Myfunc?string1&123

ISAPI-приложение будет вызывать функцию Myfunc и передавать ей в качестве параметров три значения: первым параметром всегда будет указатель на HTTP-контекст, а далее будут следовать параметры, указанные в HTTP-запросе. В данном примере это два параметра: string1 и 123. Между собой параметры разделяются символом &.

Создание ISAPI-приложения

Для того чтобы создать ISAPI-приложение, иногда также называемое ISAPI- расширением, следует:

  1. создать новый проект;
  2. в диалоге New Project выбрать шаблон создаваемого документа MFC ISAPI Extension Dll;
  3. перейти на страницу Object Setting мастера ISAPI Extension Wizard и установить флажок Generate a server extension object. В результате выполненных действий мастер ISAPI Extension Wizard сформирует шаблон ISAPI-приложения. В заголовочном файле StdAfx.h, который добавляется в шаблон любого приложения, использующего MFC-библиотеку, указана строка #include <afxisapi.h> - она выполняет подключение файла afxisapi.h, который объявляет следующие классы, поддерживающие работу с HTTP-запросами:
class ChtmlStream.
class ChttpServerContext.
class ChttpServer.
class ChttpFilterContext.
class ChttpFilter.
class CHttpArgList.

ISAPI-приложение создается как DLL-библиотека. Класс, выполняющий обработку HTTP-запроса и формирующий динамическую HTML-страницу, наследуется от класса CHttpServer.

В следующем листинге приведен код заголовочного файла и файла реализации класса, наследуемого от CHttpServer. В автоматически сформированный код ISAPI-приложения внесены изменения, которые добавляют в создаваемую HTML-страницу две строки текста и форму, содержащую элемент управления.

Листинг:

// Заголовочный файл MyISAPI_1.h
#pragma once
#include "resource.h"
class CMyISAPI_1Extension : public CHttpServer
{
public:
	CMyISAPI_1Extension();    // Конструктор
	~CMyISAPI_1Extension();
public:
	virtual BOOL GetExtensionVersion(HSE_VERSION_INFO* pVer);
	virtual BOOL TerminateExtension(DWORD dwFlags);
	void Default(CHttpServerContext* pCtxt);
	DECLARE_PARSE_MAP()
};
// Файл реализации MyISAPI_1.cpp 
#include "stdafx.h"
#include "MyISAPI_1.h"
CWinApp theApp;    // Объект "приложение"
BEGIN_PARSE_MAP(CMyISAPI_1Extension, CHttpServer)   // Таблица 
													// обработки команды
	// TODO: место для определения ON_PARSE_COMMAND() и 
	// ON_PARSE_COMMAND_PARAMS() 
	ON_PARSE_COMMAND(Default, CMyISAPI_1Extension, ITS_EMPTY)
	DEFAULT_PARSE_COMMAND(Default, CMyISAPI_1Extension)
END_PARSE_MAP(CMyISAPI_1Extension)
CMyISAPI_1Extension theExtension;    // Только один объект 
									     //ISAPI-расширение класса, 
								     // наследуемого от  CHttpServer
CMyISAPI_1Extension::CMyISAPI_1Extension(){   }  	// Конструктор
CMyISAPI_1Extension::~CMyISAPI_1Extension() {   }
BOOL CMyISAPI_1Extension::GetExtensionVersion(HSE_VERSION_INFO* pVer)
{   // Вызов метода базового класса
   CHttpServer::GetExtensionVersion(pVer);
   // Загрузка строки описания
   TCHAR sz[HSE_MAX_EXT_DLL_NAME_LEN+1];
   ISAPIVERIFY(::LoadString(AfxGetResourceHandle(), // Макро - если 
    IDS_SERVER, sz, HSE_MAX_EXT_DLL_NAME_LEN)); // 0,то завершение
    _tcscpy(pVer->lpszExtensionDesc, sz);             
    return TRUE;
}
BOOL CMyISAPI_1Extension::TerminateExtension(DWORD dwFlags)
{ // Метод класса CHttpServer - позволяет выполнить завершение
	// потоков и работы ISAPI-расширения 
    return TRUE;
}
// CMyISAPI_1Extension : методы обработчики 
// Код формируемой HTML-страницы записывается методом Default 
// в поток вывода
void CMyISAPI_1Extension::Default(CHttpServerContext* pCtxt)
{
    StartContent(pCtxt);   // Начало HTML-страницы
    WriteTitle(pCtxt);     // Формирование значения тега TITLE
                         // _T - для Unocode конвертируется в L
    *pCtxt << _T(" HTML-page from ");		// Первая строка 
                                    	//HTML-страницы
    *pCtxt << _T("ISAPI-application ");
    // Формирование строки HTML-документа для отображения формы
*pCtxt << _T("<FORM> <INPUT TYPE='text' SISE=30 </FORM>");
    EndContent(pCtxt);   // Завершение HTML-страницы
}
// Следующие строки вставляются мастером 
// ISAPI Extension Wizard 
// только на тот случай, если ISAPI-расширение не будет 
// использовать MFC-бибиотеку. 
// В противном случае эти строки можно удалить
/****
static HINSTANCE g_hInstance;
HINSTANCE AFXISAPI AfxGetResourceHandle()
{	return g_hInstance;}
BOOL WINAPI DllMain(HINSTANCE hInst, ULONG ulReason,   // Точка 
					LPVOID lpReserved)		// входа в DLL-модуль
{
	if (ulReason == DLL_PROCESS_ATTACH)
	{		g_hInstance = hInst;	}
	return TRUE;
}
****/
Листинг 28.1.

Каждый запрос обрабатывается некоторой функцией. При вызове такой функции, в качестве параметра ей передается объект типа CHttpServerContext. Для каждой такой функции должен быть указан вход в таблице обработки команд.

< Лекция 27 || Лекция 28: 1234
Александр Демьяненко
Александр Демьяненко

Можно ли сдавать один и тот же тест несколько раз?
Или же один и тот же тест можно сдать лишь однажды?

Максим Стогний
Максим Стогний

Добрый день!

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

тип_метода (имя_класса::*имя_метода_указателя)
    (список параметров);
тип_функции (*имя_ функции_указателя)
    (список параметров);

при этом можно было  тип_функции во втором описании заменить на тип_метода? Т.е.:

тип_метода (*имя_ метода_указателя)
    (список параметров);