Можно ли сдавать один и тот же тест несколько раз? |
Серверные приложения
Взаимодействие по протоколу 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- расширением, следует:
- создать новый проект;
- в диалоге New Project выбрать шаблон создаваемого документа MFC ISAPI Extension Dll;
- перейти на страницу 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. Для каждой такой функции должен быть указан вход в таблице обработки команд.