[c++] Класс Веб-сервер

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by ZaCo, 28 Jun 2007.

  1. ZaCo

    ZaCo Banned

    Joined:
    20 Jun 2005
    Messages:
    737
    Likes Received:
    336
    Reputations:
    215
    Вчера возникла задача обслуживания своего приложения через веб, но чтобы не возиться с локализацией я решил написать более-менее универсальный класс на си++ для решения этой задачи. Класс представляет собой набор методов для воссоздания модели настоящего веб-сервера, тут конечно ни о каком соответствии с rfc и речи быть не может, однако для получения и соответствующей обработки переменных передаваемых в get\post\cookie его в общем-то хватает.
    Пример программы, которая складывает два числа и выводит ip-адрес пользователя на странице:
    Code:
    #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;
     }
    }
    
    Сначала идет описание прототипа пользовательской функции:
    Code:
    void func(int id,var_map * vars,p_selfOut outF)
    
    Ее задача состоит как раз-таки в обработке переданных переменных и выводе соответствующей странички в качестве ответа. Передав конструктору адрес функции, при каждом новом запросе к веб-серверу, объект класса cWebs сам вызовет функцию и указатель на обьект типа карта (map), (предоставляя тем самым удобный пхп-подобный доступ к переменным), адрес-функцию Out и некоторое int значение id, которое функция сама должна передать в Out для вывода данных в ответ на исходный хттп-запрос. Прототип функции Out:

    Code:
    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/
     
    #1 ZaCo, 28 Jun 2007
    Last edited: 2 Sep 2007
    3 people like this.
  2. Pochka

    Pochka Banned

    Joined:
    26 Nov 2005
    Messages:
    27
    Likes Received:
    7
    Reputations:
    -2
    :D откуда скопипастил?
     
  3. ZaCo

    ZaCo Banned

    Joined:
    20 Jun 2005
    Messages:
    737
    Likes Received:
    336
    Reputations:
    215
    не помню,

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