PDA

Просмотр полной версии : [c++] Класс Веб-сервер


ZaCo
28.06.2007, 15:36
Вчера возникла задача обслуживания своего приложения через веб, но чтобы не возиться с локализацией я решил написать более-менее универсальный класс на си++ для решения этой задачи. Класс представляет собой набор методов для воссоздания модели настоящего веб-сервера, тут конечно ни о каком соответствии с rfc и речи быть не может, однако для получения и соответствующей обработки переменных передаваемых в get\post\cookie его в общем-то хватает.
Пример программы, которая складывает два числа и выводит ip-адрес пользователя на странице:

#include <winsock2.h>
#include <string>

#include "swebs.hpp"
namespace std
{

typedef map <string, string> var_map;
void func(int,var_map *,p_selfOut);

void func(int id,var_map * vars,p_selfOut outF)
{
string out_s;

out_s="HTTP/1.1 200 OK\n";
out_s+="Connection: close\n";
out_s+="Content-Type: text/html\n\n";
outF(id, out_s.c_str(), out_s.length());


var_map & Vars=*vars;

string data1=Vars["a"],data2=Vars["b"];

if(data1.empty()||data2.empty())//form
{
out_s="Welcome: "+Vars["REMOTE_ADDR"]+"<br>\n";
outF(id, out_s.c_str(), out_s.length());

out_s="<html> <head> <title>WebS test</title> </head> <form method=post> <input type=text name=a> <input type=text name=b> <input type=submit> </form></html>";
outF(id, out_s.c_str(), out_s.length());
}
else
{
char out_s[256];
strcpy(out_s,"<b>sum is: </b>");
sprintf(&out_s[strlen(out_s)],"%d",atoi(data1.c_str())+atoi(data2.c_str()));
outF(id, out_s, strlen(out_s));
}

delete vars;
}

int main(int argc, char * argv[])
{
WSADATA WSA;
if(WSAStartup(MAKEWORD(2,2), &WSA) != 0) return 0;
//
cWebs server(func, 6669);
bool ok=server.Bind();
if(ok) server.Listen();
else puts("binding error");
return 0;
}
}


Сначала идет описание прототипа пользовательской функции:

void func(int id,var_map * vars,p_selfOut outF)


Ее задача состоит как раз-таки в обработке переданных переменных и выводе соответствующей странички в качестве ответа. Передав конструктору адрес функции, при каждом новом запросе к веб-серверу, объект класса cWebs сам вызовет функцию и указатель на обьект типа карта (map), (предоставляя тем самым удобный пхп-подобный доступ к переменным), адрес-функцию Out и некоторое int значение id, которое функция сама должна передать в Out для вывода данных в ответ на исходный хттп-запрос. Прототип функции Out:


void Out(int ,const char *, int);


Второй аргумент представляет собой строку-указатель, третий длину строки.

Несмотря на то, что класс обеспечивает лишь элементарные возможности http-запроса, он в то же время предоставляет и простую их обработку пользовательской функцией. Все переданные переменные сохраняются в карте *vars при этом метод которым они передавались не учитывается. Одновременно через *vars имеется доступ к переменным окружения: REMOTE_ADDR (ИП пользователя) и GET_FILE (запрашиваемый файл в запросе).

ps иерархия переменных: get, cookie, post. то есть, значение get-переменной 'a', перепишется значением post-переменной 'a', если таковая имеется.



Исходники: http://zaco.itdefence.ru/webs/

Pochka
28.06.2007, 17:29
WSAStartup(MAKEWORD(2,2), &WSA)

:D откуда скопипастил?

ZaCo
28.06.2007, 18:36
не помню,

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