PDA

Просмотр полной версии : [релиз] Micro Web Server DLL


slesh
23.11.2009, 22:36
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 в папке с программой.

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;



Пример использование в С++
Для С++ по подобной системе.

#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 )

=Zeus=
23.11.2009, 23:17
Отличная стьтья, очень хороший пример работы с сокетами на С++.
Спасибо.

bons
24.11.2009, 01:57
жаль что максимальный поддерживаемый размер файла - 2 гига. Серьезный порнофильм уже не скачаешь с такими ограничениями :(

ErrorNeo
24.11.2009, 02:54
жаль что максимальный поддерживаемый размер файла - 2 гига. Серьезный порнофильм уже не скачаешь с такими ограничениями :(ахахха.

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

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

*thumbs_up* *respect*

скоро можно будет открывать целый подраздел в кодинге - "статьи\релизы". И это будет true

slesh
24.11.2009, 10:59
2 bons если тебе нужны файлы оооочень большого размера, то можеш сам ыбстро подправить. у меня в 2-х местах юзается функция GetFileSize без указания адреса буфера для старшей части размера. По этому получаю только младшую его часть, ограниченную 4-мя гигами.

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

Но вообще, сейчас подправлю и перезалью.

slesh
24.11.2009, 11:34
Исправил. теперь вроде сервак должен поддерживать файлы любого размера

bons
24.11.2009, 11:35
ахахха.

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

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

PS вы тут писали: язык программирования - С++ это не С++ а С

slesh
24.11.2009, 11:49
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 серваков врядли ктото будет. А работа с сетью - если будет качаться большой файл при большом буфере и малой скорости коннекта, то тут без потока не обойтись.

slesh
24.11.2009, 11:59
2 bons

Зачем вы тут приводите типы? обе переменные типа char* и приведение тут совсем не нужно. И не только тут. Например строчку
Код:
tmp = (char*)((ULONG)tmp + (ULONG)len);
легко можно записать так:
Код:
tmp += len;


ты думаешь я об этом не знаю? Впервые столкнулся с такой проблемой в DDK когда в дровах такая запись не подходила. И дело там было в том, что tmp += len; и tmp = (char*)((ULONG)tmp + (ULONG)len); давали совершенно разные результаты. Юзался тогда компилятор MS DDK XP. C тех пор начал везде писать код в подобном виде


язык программирования - С++
это не С++ а С

я прекрасно знаю что я пишу в Сишном стиле а не С++
Сказано это было потому что компилятору даются указания что это С++ код а не С
Хотя будет компилиться нормально и как Си

Sams
24.11.2009, 12:46
А я как раз изучаю работу с сокетами! Прям подарок для меня :D
Респект, а так же отдельное спасибо за пример работы с Delphi.

slesh
28.11.2009, 01:50
2 Sams если ты изучаеш делфи, то лучше найти какойнить проект который написан на делфи, а не на Си, чтобы потом небыло у тебя путаници, которая происходит из-за того что в Си больше юзаются указатели.