[релиз] Micro Web Server DLL

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by slesh, 23 Nov 2009.

  1. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Micro Web Server DLL

    Что это и для чего это?
    1) Это небольшой веб сервер реализованный в виде DLL
    2) Может использовать как добавочная нагрузка на разного рода программы, где необходим свой простенький веб сервер, преимущественно для скачевание файлов. А также можно сделать его полезной нагрузкой шпионских программ или других ползучих гадов )

    Характеристики:
    1) чистый размер DLL - 4608
    2) язык программирования - С++
    3) среда разработки - MS Visual Studio 2008 Pro
    4) 2 функции - остановка сервера и запуск сервера
    5) Поддерживаемые ОС - Windows 98SE - Windows 7
    6) Возможность использования в любых программах на любых языках (ASM, Delphi, C, C++, VB и другие компилируемые языки)
    7) Сокетная система - WinSock2
    8) зависимость от DLL - WS2_32.DLL, KERNEL32.DLL, USER32.DLL. Другими словами - всё стандартное, всё системное.

    Возможности:
    1) неограниченное кол-во работающих параллельно серверов (сколько система позволит)
    2) Запуск и остановка любого сервера в любое время
    3) задание порта для сервера
    4) задание таймаута на получение команды от клиента
    5) установка своей корневой диры для каждого сервера
    6) задание максимального кол-ва пользователей одновременно обрабатываемых сервером.
    7) установку размера буфера при отдаче файлов. (но не менее 1024 байт)
    8) максимальный поддерживаемый размер файла - сколько позволит винда. Теоретически должно работать с файлами > 4 гигов
    9) показ содержимого папки
    10) поддержка русскоязычных названий папок и файлов. Теоретически вообще любые кодировки должны пахать, потому что используется widechar.

    Чего не умеет:
    1) никакие запросы кроме GET не поддерживаются
    2) нет поддержки докачки файлов.
    3) нет поддержки файлов размером больше 2 гигов.
    4) никакие php, perl и прочие cgi не поддерживаются
    5) сервер настроен так, что все файлы он отдает на скачевание а не на показ. т.е. я поставил application/octet-stream для всех типов файлов. Но по желанию каждый может изменить.

    Функции DLL
    function StartServer(var id : dword; ip : dword; port : word; MaxClients : integer; TimeOut : dword; BufSize : dword; MainDir : pwidechar):dword;

    Функция возвращает результат запуска сервера. Константы описаны ниже.
    Параметры:
    id - в переменную будет записан дескриптор сервера
    ip - сетевой интерфейс на котором будет слушаться порт. 0 - на всех.
    port - порт для сервера
    MaxClients - макс число одновременно подсоединенных клиентов к данному серверу
    TimeOut - таймаут на получение команды от клиента в миллисекундах. т.е. 1000 = 1 сек
    BufSize - размер буфера при передаче файлов
    MainDir - корневая папка сервера

    function StopServer(id : dword) : dword; - остановка сервера.
    id - дескриптор сервера

    Пример использование в Delphi
    Разместить DLL в папке с программой.
    Code:
    const // коды ошибок
      SERVER_STATUS_OK                  = $FFFFFFF0;
      SERVER_STATUS_FOLDER_ERROR        = $FFFFFFF1;
      SERVER_STATUS_CREATE_SOCKET_ERROR = $FFFFFFF2;
      SERVER_STATUS_BIND_ERROR          = $FFFFFFF3;
      SERVER_STATUS_LISTEN_ERROR		  	= $FFFFFFF4;
      SERVER_STATUS_ALLOC_MEM_ERROR		  = $FFFFFFF5;
      SERVER_STATUS_CREATE_THREAD_ERROR	= $FFFFFFF6;
      SERVER_STATUS_ID_ERROR				    = $FFFFFFF7;
    // остановка сервера
      function StopServer(id : dword) : dword; stdcall; external 'WebServ.dll';
    
    // запуск сервера
      function StartServer(var id : dword; ip : dword; port : word; MaxClients : integer; TimeOut : dword; BufSize : dword; MainDir : pwidechar):dword; stdcall; external 'WebServ.dll';
    
    var
      Server_1 : dword; 
      Server_2 : dword;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      status : dword;
    begin
      // запустить сервер.
      status := StartServer(Server_1, 0, 666, 10, 30000, 4096, 'c:\');
      if status <> SERVER_STATUS_OK then
      begin
        ShowMessage('Server 1 Start Error. Code = ' + inttohex(status, 8));
      end;
    
      status := StartServer(Server_2, 0, 667, 10, 30000, 4096, 'd:\');
      if status <> SERVER_STATUS_OK then
      begin
        ShowMessage('Server 2 Start Error. Code = ' + inttohex(status, 8));
      end;
    
    end;
    
    // остановка
    procedure TForm1.Button2Click(Sender: TObject);
    var
      status : dword;
    begin
      status := StopServer(Server_1);
      if status <> SERVER_STATUS_OK then
      begin
        ShowMessage('Server 1 Stop Error. Code = ' + inttohex(status, 8));
      end;
    
      status := StopServer(Server_2);
      if status <> SERVER_STATUS_OK then
      begin
        ShowMessage('Server 2 Stop Error. Code = ' + inttohex(status, 8));
      end;
    end;
    
    
    Пример использование в С++
    Для С++ по подобной системе.
    Code:
    #define SERVER_STATUS_OK					0xFFFFFFF0
    #define SERVER_STATUS_FOLDER_ERROR			0xFFFFFFF1
    #define SERVER_STATUS_CREATE_SOCKET_ERROR	0xFFFFFFF2
    #define SERVER_STATUS_BIND_ERROR			0xFFFFFFF3
    #define SERVER_STATUS_LISTEN_ERROR			0xFFFFFFF4
    #define SERVER_STATUS_ALLOC_MEM_ERROR		0xFFFFFFF5
    #define SERVER_STATUS_CREATE_THREAD_ERROR	0xFFFFFFF6
    #define SERVER_STATUS_ID_ERROR				0xFFFFFFF7
    
    ULONG __stdcall StartServer(ULONG* id, ULONG ip, USHORT port, LONG MaxClients, ULONG TimeOut, ULONG BufSize, wchar_t * MainDir)
    ULONG __stdcall StopServer(ULONG id)
    .....................
     ULONG Server;
     
     StartServer(&Server_1, 0, 666, 10, 30000, 4096, L"c:\\");
    .......................
    
    На последок
    Если компилить как exe то размер будет 3,5 кила.
    В принципе работает норм. Покрайней мере при тестировании. Кто пробовал, отпишите.

    В архиве вы найдете файлы:
    WebServ.cpp - исходник DLL
    WebServ.def - вспомогательный файл
    WebServ.dll - откомпиленная DLL
    WebServ.h - хидер
    WebServ.vcproj - файл проекта

    (С) SLESH 2009 )
     

    Attached Files:

    #1 slesh, 23 Nov 2009
    Last edited: 24 Nov 2009
    14 people like this.
  2. =Zeus=

    =Zeus= Member

    Joined:
    10 Aug 2009
    Messages:
    213
    Likes Received:
    54
    Reputations:
    5
    Отличная стьтья, очень хороший пример работы с сокетами на С++.
    Спасибо.
     
  3. bons

    bons Elder - Старейшина

    Joined:
    20 Dec 2007
    Messages:
    286
    Likes Received:
    121
    Reputations:
    21
    жаль что максимальный поддерживаемый размер файла - 2 гига. Серьезный порнофильм уже не скачаешь с такими ограничениями :(
     
  4. ErrorNeo

    ErrorNeo Elder - Старейшина

    Joined:
    2 May 2009
    Messages:
    923
    Likes Received:
    838
    Reputations:
    402
    ахахха.

    Да, bons, не думал, что ты настолько суров, чтобы ломать людей, ставить им веб-серваки, и все это - только для того, чтобы тырить у них порно! :D

    <релиз как всегда на высоте, +1 в золотой фонд ачата>
    очень не часто можно найти такие вещи с сурсами

    *thumbs_up* *respect*

    скоро можно будет открывать целый подраздел в кодинге - "статьи\релизы". И это будет true
     
    #4 ErrorNeo, 24 Nov 2009
    Last edited: 24 Nov 2009
    1 person likes this.
  5. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 bons если тебе нужны файлы оооочень большого размера, то можеш сам ыбстро подправить. у меня в 2-х местах юзается функция GetFileSize без указания адреса буфера для старшей части размера. По этому получаю только младшую его часть, ограниченную 4-мя гигами.

    Вообще тут чтото непонятное. Одна дока пишет что 2 гига максимум, другая 4 гига.

    Но вообще, сейчас подправлю и перезалью.
     
    #5 slesh, 24 Nov 2009
    Last edited: 24 Nov 2009
  6. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Исправил. теперь вроде сервак должен поддерживать файлы любого размера
     
  7. bons

    bons Elder - Старейшина

    Joined:
    20 Dec 2007
    Messages:
    286
    Likes Received:
    121
    Reputations:
    21
    когда-то писал подобную вещь для подобных целей, только это был ftp-сервер и на делфи(тоже в виде DLL). И знаете, у 95% это единственное ценное на винте.
    По теме: slesh у вас там странный очень код:
    Code:
    len = recv(sock, tmp, 4096 - fulllen, 0); // считаем данные
    if (len > 0) // если данных больше 0
    {
    	tmp = (char*)((ULONG)tmp + (ULONG)len); // переместим указатель в нутри буфера
    	fulllen += len; // сумарный размер 
    }
    вот здесь принимаются данные и по логике переменная fulllen вполне может оказаться равной 4096. А здесь
    Code:
    input_buf[fulllen] = 0x00;
    в таком случае будет обнулен уже не элемент массива input_buf а нечто другое. А содержимое input_buf уже будет не ASCIIZ-строкой. Возможно это фигня и ничего плохого из-за этого не случится(я не смотрел дальше) но все же неприятно ;)
    Еще не совсем понятно зачем переписывать стандатртную функцию strstr.
    Начало функции my_strstr мне тоже нравится
    Code:
    char *cp = (char *) str1;
    Зачем вы тут приводите типы? обе переменные типа char* и приведение тут совсем не нужно. И не только тут. Например строчку
    Code:
    tmp = (char*)((ULONG)tmp + (ULONG)len);
    легко можно записать так:
    Code:
    tmp += len;
    Ну я детально не разбирал, наверно там еще есть ченить интересное. А так вообще сервер норм, пригоден для тыренья порнухи в локалке, да. Только опять жже почему вы все делаете на потоках? microsoft предоставила уйму API чтобы вы так не делали: WSAEventSelect, WSAAsyncSelect и много других. А вы вот предпочитаете юзать самую примитивную модель сетевого приложения

    PS вы тут писали:
    это не С++ а С
     
    #7 bons, 24 Nov 2009
    Last edited: 24 Nov 2009
  8. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 bons
    1) там не странный код, а код который считывает http запрос до того как встретится \r\n\r\n при условии что максимум 4096 можно считать.
    Код построен таким образом, чтобы учесть тот факт что запрос может быть разбит на небольшие части.

    2) с input_buf[fulllen] = 0x00; ты прав. Может быть глюк. но при условии что будут посланы именно 4096 байт. мне достаточно сделать input_buf[fulllen-1] = 0x00; всё равно мне конец не нужен или ограничить чтение 4095 байтами

    3) char * my_strstr(char * str1, char * str2) - взята из исходников CRT либы VS 2008 Pro
    когда юзал либу, то почему-то кода становилось больше, чем когда извлек эту функцию.
    По поводу кривизны функции этой - пиши жалобу в MS может исправят )

    4) не привык както к асинхронным сокетам, по этому использую по старинке всё)
    Тем более что тут это не критично.
    т.к. юзать больше 1-2 серваков врядли ктото будет. А работа с сетью - если будет качаться большой файл при большом буфере и малой скорости коннекта, то тут без потока не обойтись.
     
    #8 slesh, 24 Nov 2009
    Last edited: 24 Nov 2009
  9. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 bons
    ты думаешь я об этом не знаю? Впервые столкнулся с такой проблемой в DDK когда в дровах такая запись не подходила. И дело там было в том, что tmp += len; и tmp = (char*)((ULONG)tmp + (ULONG)len); давали совершенно разные результаты. Юзался тогда компилятор MS DDK XP. C тех пор начал везде писать код в подобном виде

    я прекрасно знаю что я пишу в Сишном стиле а не С++
    Сказано это было потому что компилятору даются указания что это С++ код а не С
    Хотя будет компилиться нормально и как Си
     
    #9 slesh, 24 Nov 2009
    Last edited: 24 Nov 2009
    2 people like this.
  10. Sams

    Sams Member

    Joined:
    18 Apr 2009
    Messages:
    247
    Likes Received:
    70
    Reputations:
    17
    А я как раз изучаю работу с сокетами! Прям подарок для меня :D
    Респект, а так же отдельное спасибо за пример работы с Delphi.
     
  11. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 Sams если ты изучаеш делфи, то лучше найти какойнить проект который написан на делфи, а не на Си, чтобы потом небыло у тебя путаници, которая происходит из-за того что в Си больше юзаются указатели.