Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Web интерфейс программы 
:(
    Опции темы
TheDestroyer
Дата 13.5.2009, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Нужно сделать web-интерфейс для программы. Т.е. чтобы заходя браузером на определенный порт компьютера, где запущена эта программа можно было увидеть сайт, через который можно управлять данной программой. Также нужно обеспечить кроссплатформенность программы (windows, linux). Написание программы на php + веб сервер не подходит. Т.к. необходимо иметь программу и веб сервер в одном комплекте.
Вопросы:
1. Если писать программу на Borland C++, как начать?
Вроде нужно создать новый проект:  File - New - Other - web Server Application. Тут сразу встает вопрос, какой тип выбрать далее. Т.к. я не собираюсь писать ни CGI скрипт, ни библиотеку к апаче, а самостоятельный exe-шник, то, похоже, надо выбрать последний пункт - Web App Debugger Executable... Подскажите что и как, плз?

2. По кроссплатформенности, по идее, можно написать windows приложение и для запуска под linux использовать WINE- эмулятор windows (не совсем эмулятор, как они пишут у себя на сайте). Тогда сразу встает вопрос, если я открываю порт на компьютере API функциями, то откроется ли порт под linux через этот WINE?

3. Если для кроссплатформенности писать не на Borland C++, а на чем-нибудь другом, то на чем? Сразу на ум приходит .NET, ведь оно для кроссплатформенности вроде как и сделано. Но я в нем новичек. Посоветуйте, стоит ли заниматься написанием данной программы например на C# .NET или все-таки на c++ не так уж и сложно реализовать?

Приветствуются все советы и ссылки
PM MAIL   Вверх
jonie
Дата 13.5.2009, 18:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 15
Всего: 118



пример в аттаче (архив 7z)

Присоединённый файл ( Кол-во скачиваний: 47 )
Присоединённый файл  pfm.7z.doc 42,51 Kb


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
Vasay
Дата 13.5.2009, 19:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2097
Регистрация: 8.3.2006

Репутация: нет
Всего: 73



TheDestroyer, 

Цитата

1. Если писать программу на Borland C++, как начать?
Вроде нужно создать новый проект:  File - New - Other - web Server Application. Тут сразу встает вопрос, какой тип выбрать далее. Т.к. я не собираюсь писать ни CGI скрипт, ни библиотеку к апаче, а самостоятельный exe-шник, то, похоже, надо выбрать последний пункт - Web App Debugger Executable... Подскажите что и как, плз?


Только вчера был пост на эту тему:
http://forum.vingrad.ru/forum/topic-259024.html

Цитата

3. Если для кроссплатформенности писать не на Borland C++, а на чем-нибудь другом, то на чем? Сразу на ум приходит .NET, ведь оно для кроссплатформенности вроде как и сделано. Но я в нем новичек. Посоветуйте, стоит ли заниматься написанием данной программы например на C# .NET или все-таки на c++ не так уж и сложно реализовать?


Есть, конечно, mono для C#, но он сильно отстает от  MS версии .NET, да и с лицензией там не так чисто. 
Если кросплатформенность нужна - то это либо Java (кстати, есть классы, реализующие функционал web-сервера), либо Qt (и ему подобные кросплатформенные библиотеки).


п.с. а вы уверены, что вам нужен такой изврат как веб-сервер в вашей программе?

Это сообщение отредактировал(а) Vasay - 13.5.2009, 19:30


--------------------
Придумать идеальную защиту от дурака невозможно, дураки, наудивление, изобретательны.
PM MAIL   Вверх
Любитель
Дата 13.5.2009, 19:41 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 24
Всего: 92



Цитата(Vasay @  13.5.2009,  19:29 Найти цитируемый пост)
Если кросплатформенность нужна - то это либо Java (кстати, есть классы, реализующие функционал web-сервера), либо Qt (и ему подобные кросплатформенные библиотеки).

Python/Ruby почему не рассматриваются?!

Цитата(Vasay @  13.5.2009,  19:29 Найти цитируемый пост)
п.с. а вы уверены, что вам нужен такой изврат как веб-сервер в вашей программе?

Почему изврат? WebUI управления плеером или торрент-клиентом вещь очень типичная...


--------------------
PM MAIL ICQ Skype   Вверх
Vasay
Дата 13.5.2009, 20:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2097
Регистрация: 8.3.2006

Репутация: нет
Всего: 73



Цитата

Python/Ruby почему не рассматриваются?!

Python - думаю тоже возможно. Просто я с ним и его возможностями незнаком.
Ruby - в те времена когда я им интересовался, для написания веб-сервера он был не пригоден, так как имел проблемы с многопоточностью.


Цитата

Почему изврат? WebUI управления плеером или торрент-клиентом вещь очень типичная... 


Может, с "изварат" я погорячился, иногда такой подход может быть необходим, переформулирую вопрос - TheDestroyer а Вы точно уверены, что Вам это нужно (может использование веб-сервера будет удобней, или вообще запустить приложение в контексте сервера приложений)?

Это сообщение отредактировал(а) Vasay - 13.5.2009, 20:33


--------------------
Придумать идеальную защиту от дурака невозможно, дураки, наудивление, изобретательны.
PM MAIL   Вверх
Vasay
Дата 13.5.2009, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2097
Регистрация: 8.3.2006

Репутация: нет
Всего: 73



Да, если речь идет об веб-интерфейсе к программе (т.е. веб-сервере внутри программы), то начинать надо не так:
Цитата

1. Если писать программу на Borland C++, как начать?
Вроде нужно создать новый проект:  File - New - Other - web Server Application. Тут сразу встает вопрос, какой тип выбрать далее. Т.к. я не собираюсь писать ни CGI скрипт, ни библиотеку к апаче, а самостоятельный exe-шник, то, похоже, надо выбрать последний пункт - Web App Debugger Executable... Подскажите что и как, плз?


А создать обычное десктоп приложение (с GUI или без - зависит от Вашей задачи), и внутри него, в отдельном потоке реализовать вебсервер -  открыть сокет на прослушивание определенного порта и обрабатывать входящие запросы... Недавно на этом форуме мелькали примеры, как это реализуется на с++ и Java. 

Однако, я не стал бы использовать Builder для кросплатформенной задачи. Если есть желание писать именно на c++, то посмотрите в сторону qt 

Вот, кстати, примерчик: http://doc.crossplatform.ru/qt/4.5.0/netwo...tuneserver.html. Для работы из веб-браузера потребуется реализовать протокол HTTP (вот пример для QT http://doc.trolltech.com/solutions/3/qtser...ple-server.html ).

Единственный минус QT - то что требуется перекомпиляция под разные системы.  С Java проще - достаточно наличие jre в системе.

Добавлено через 13 минут и 15 секунд
В Java есть класс реализующий HTTP сервер, предназначенный как раз для реализации встроенных http серверов: http://java.sun.com/javase/6/docs/jre/api/...ge-summary.html

Это сообщение отредактировал(а) Vasay - 13.5.2009, 20:55


--------------------
Придумать идеальную защиту от дурака невозможно, дураки, наудивление, изобретательны.
PM MAIL   Вверх
TheDestroyer
Дата 14.5.2009, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Спасибо за ответы.
Поясню цель приложения, веб интерфейс это его главная функция, оно должно предоставлять пользователю управление собой через браузер. Необходим самостоятельный сервер для того, чтобы не зависеть от установленного веб сервера у пользователя (его может и не быть) и его настроек. Также надо чтобы никто не копался в исходном коде и не модифицировал его. Значит надо в конечном итоге иметь скомпилированный фаил.
jonie, это под VC++?
Про Qt даже не слышал, интересное решение по кроссплатформенности.
Получается по требованиям отвечают так:
Самостоятельный веб сервер: BC++, .NET, Java, Qt, Python, Ruby(?)
Кроссплатформенность: BC++((?)Через WINE), .NET((?) необходим Mono), Java, Qt, Python, Ruby
В принципе, перекомпиляция под разные операционные системы не критична.
Защита: BC++, .NET, Java, Qt, Python(?), Ruby(?). С Ruby дело не имел, на Python-е кое-что делал, но там все в исходных кодах, по которым при запуске среды создавались откомпилированные файлы и они уже выполнялись. Наверное для защиты можно распространять только откомпилированные файлы.

У кого есть опыт или возможность проверить будет ли корректно работать созданный в BC++ 2009 веб сервер под Linux (из под WINE), сообщите, плз.

Пока изучаю все по данной теме. Все советы, примеры и ссылки приветствуются.
PM MAIL   Вверх
isergey
Дата 14.5.2009, 13:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 30
Регистрация: 28.5.2008

Репутация: нет
Всего: нет



Уважаемый. Для того чтобы управлять приложением через веб интерфейс, тебе нужно запустить в нем веб-сервер. Благо, это позволяет сделать множество библиотек. В принципе протокол HTTP не такой уж и сложный, так что ты можешь сделать его минимальную реализацию и сам. Крутиться твой сервер будет либо отдельным потоком, либо отдельным приложением. В первом случае, полученные данные через HTTP запрос будут изменять внутренне состояние переменных программы. Во втором случае, твой сервер общается с основной программой через какой-нибудь конфигурационный файл (программа или сервер периодически читают его и изменяют свое состояние). 

Есть в питоне, в стандартной библиотеке, simpleCGIServer. Запускаешь скрипт и у тебя работающий CGI сервер. Укажешь ему где располагается директория с CGI скриптами, а в самих скриптах обрабатывай http запросы и пиши результаты в файл общения с основной программой. CGI скрипты можешь писать на чем хочешь, но лучше на питоне, для этого там тоже есть библиотека CGI.

Удачные пример управление программой через веб интерфейс - это всем известный µTorrent http://www.utorrent.com/documentation/webui/

Конечно было бы не плохо, если бы ты в своей основной программе веб сервер сделал сам. Тогда получишь опыт работы с сетевыми сокетами и опыт работы с многопоточностью. Единственный минус в том, что такое решение может быт дырявым и не стабильным (неправильно обработал данные и все твое приложение падает). Но, как говориться, волков бояться  - в лес не ходить smile Дерзай!

ЗЫ. Только не надо использовать никакие с++ билдеры.
PM MAIL   Вверх
TheDestroyer
Дата 14.5.2009, 13:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



WebUi сам активно использую, с многопоточностью опыт работы есть.
CGI скрипты, хорошо, но не подходят из-за открытости исходного кода как и php. Так у меня есть написанный на php вариант программы, но в php под windows не работает многопоточность (forking) и исходный код не скроешь (про Zend и т.п. знаю, но это не выход в данном случае).

Склоняюсь к Qt, качаю и буду ставить. На сайте Qt они предлагают использовать их родную среду, также народ пишет, что очень удобно использовать Qt в MS VC++.
Скажите пожалуйста, какую среду для разработки лучше использовать?
PM MAIL   Вверх
isergey
Дата 14.5.2009, 13:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 30
Регистрация: 28.5.2008

Репутация: нет
Всего: нет



Я конечно не знаю, но по моему,  если ты не используешь коммерческую версию QT, тебе нужно открывать исходные коды.

А по поводу скрытия исходного кода, никто не запрещает использовать питон скрипты компилированные в байт код т.е. *.pyc
PM MAIL   Вверх
sdukshis
Дата 14.5.2009, 14:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 23.3.2009

Репутация: нет
Всего: 1



Qt - хорошая библиотека для кроссплатформенной разработки, но рассчитана она, в первую очередь, на создание клиентских приложений.

Из все платформонезависимости Вам скорее всего понадобятся только сокеты, потоки и операции с файловой системой.

Для сокетов можно использовать ASIO http://www.boost.org/doc/libs/1_39_0/doc/h...boost_asio.html
Для потоков Boost Tread http://www.boost.org/doc/libs/1_39_0/doc/html/thread.html
Для работы с файловой системой Boost Filesystem http://www.boost.org/doc/libs/1_39_0/libs/...m/doc/index.htm

К тому же открытым остается вопрос демонизации, который по разному решается на различных платформах (насколько я знаю кроссплатформенной библиотеки нет). Хотя это можно сделать в ручную.

Я думаю, что оптимальным вариантов здесь будет не использование библиотек boost или qt, а собственный платформонезависимый слой и условная компиляция.

К сожаления с Java работал очень мало. Но если все эти вопросы там хорошо решены, то выбор явно в её пользу.
PM MAIL   Вверх
Любитель
Дата 14.5.2009, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

Репутация: 24
Всего: 92



Цитата(isergey @  14.5.2009,  13:54 Найти цитируемый пост)
Я конечно не знаю, но по моему,  если ты не используешь коммерческую версию QT, тебе нужно открывать исходные коды.

Qt с 4.5 под LGPL. Ни раз уже здесь обсуждалось smile

Цитата(isergey @  14.5.2009,  13:54 Найти цитируемый пост)
А по поводу скрытия исходного кода, никто не запрещает использовать питон скрипты компилированные в байт код т.е. *.pyc 

А вот это да. Более того - нормальных декомпиляторов питона (как ни странно) мне лично найти не удалось.. Т. е. по крайней мере новичков отпугнёт (что не скажешь о яве или дотНет).


--------------------
PM MAIL ICQ Skype   Вверх
xvr
Дата 15.5.2009, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Абсолютно независимая реализация WEB сервера на голом С++ занимает около 1000 строк. Используются голые сокеты (исходник для Windows, но платформо зависимая часть winsock'а может легко быть портированна под linux и пр)
(Файлы StdAfx.* и utils.* - общие файлы всего проекта, не только WEB сервера. 90% содержимого для WEB сервера не нужно)

Присоединённый файл ( Кол-во скачиваний: 40 )
Присоединённый файл  websrv.zip 15,20 Kb
PM MAIL   Вверх
TheDestroyer
Дата 20.5.2009, 01:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Результаты поисков (могут быть полезными всем, кто ищет информацию по данной теме):
Веб серверы с исходным кодом с поддержкой серверных скриптовых языков:
http://code.google.com/p/mongoose/
http://www.lighttpd.net/

Простые веб серверы с отдельной директорией под html странички:
http://www.pion.org/projects/pion-network-library
http://www.pablosoftwaresolutions.com/html...web_server.html

Библиотеки:
http://www.webtoolkit.eu/
http://www.qtsoftware.com/
http://www.boost.org/doc/libs/1_39_0/doc/h...boost_asio.html

Интересные примеры веб серверов, webio умеет создавать единый исполняемый фаил со встроенными страничками:
http://www.codeproject.com/KB/IP/webio.aspx
http://www.codeproject.com/KB/IP/webem.aspx
http://www.adp-gmbh.ch/win/misc/webserver.html
http://xaxxon.slackworks.com/ehs/

jonie и xvr, спасибо за примеры.
Пример jonie откомпилировался, буду разбираться что к чему.
Пример xvr не получается откомпилировать, почему-то не поинимает тип WSAEVENT в tcp_server.h. Видимо, что-то надо include-ить. Компилирую в В Visual C++, в нем я новичек, так что если несложно, подскажите что не так.
Делаю так: чтобы создать проект выбираю в меню Фаил - Создать - Проект из существующего кода - добавляю все файлы в папке.
PM MAIL   Вверх
xvr
Дата 20.5.2009, 10:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



WSAEVENT определен в winsock2.h, подключается через windows.h, который в свою очередь подключается через StdAfx.h -> utils.h

В любом случае от моих сорцов надо будет отрезать лишнее (оно там есть), и приделать свое (хотя бы доступ к файлам, которые вы хотите передавать через WEB сервер - оригинал их доставал из zip архива, помещенного в ресурсы exe'ника)

PM MAIL   Вверх
TheDestroyer
Дата 21.5.2009, 00:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Продолжаю разбирать пример xvr:
На сколько я понял web_server.h и web_server.cpp - реализация поддержки http протокола, tcp_server.h и tcp_server.cpp - реализация сокетов и многопоточности.
То, чего нехватает (лишнее) - убрал из StdAfx.cpp (класс InitSeqBuilder), остальное в utils пока не мешает, уберу позже.
Проблему с нераспознанием типа решил установкой #include <winsock2.h> перед #include <windows.h> в utils.h
Теперь много ошибок при компиляции типа: 
Код

1>Компоновка...
1>tcp_server.obj : error LNK2019: ссылка на неразрешенный внешний символ __imp__setsockopt@20 в функции "public: bool __thiscall TCP_Server::do_init(int)" (?do_init@TCP_Server@@QAE_NH@Z)
1>web_server.obj : error LNK2001: неразрешенный внешний символ "__imp__setsockopt@20"
1>tcp_server.obj : error LNK2019: ссылка на неразрешенный внешний символ __imp__listen@8 в функции "public: bool __thiscall TCP_Server::do_init(int)" (?do_init@TCP_Server@@QAE_NH@Z)

т.е. не принимает функции setsockopt, listen,... Как это поправить?


Еще несколько вопросов:
1. Что описывает класс HTTP_SendAns? Его функции вижу, а как это одним словом называется не пойму..
2. Что означает последний параметр в функции send_file_data(d,find_file_type(get_file_ext(fname)),false); ? Похоже, что в хэдер будет добавлено Last-Modified: %s. Last-Modified — время последнего изменения пересылаемых данных. В каком случае это может пригодиться?
3. Мой сайт построен так, что он состоит не из отдельных html страничек, а из php файлов, которые выдают информацию на страницу в зависимости от запросов пользователя. Используется довольно много Javascript и Ajax. В данном случае вместо php используется C++. Вопрос: место куда лучше вставить динамическую генерацию кода страничек этоHTTP_SendAns::send_file1(string fname) ? Т.к. там 
string d=find_resource("web\\"+fname);
в переменной d, как я понял хранится код странички, которую сервер отошлет пользователю. Получается здесь надо вставить мою функцию, которая будет динамически создавать сожержимое страницы. Но для генерации этого содержимого надо знать переменные POST и GET запросов, хорошо бы знать cookies для идентификации пользователя (как сессии в php) и хранения некоторых его переменных. В каком месте доступны эти переменные ( POST и GET запросов) и есть ли здесь реализация cookies?


Это сообщение отредактировал(а) TheDestroyer - 21.5.2009, 00:29
PM MAIL   Вверх
Andrey44
Дата 21.5.2009, 08:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1501
Регистрация: 4.12.2006
Где: На работе

Репутация: 2
Всего: 26



Цитата

т.е. не принимает функции setsockopt, listen,... Как это поправить?

Код

#pragma comment(lib, "Ws2_32.lib")



--------------------
????? ??, ??????? ?????.  smile 
PM MAIL WWW ICQ   Вверх
xvr
Дата 21.5.2009, 12:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(TheDestroyer @ 21.5.2009,  00:26)
Продолжаю разбирать пример xvr:
На сколько я понял web_server.h и web_server.cpp - реализация поддержки http протокола, tcp_server.h и tcp_server.cpp - реализация сокетов и многопоточности.

Угу

Цитата

т.е. не принимает функции setsockopt, listen,... Как это поправить?
Уже ответили - прилинковать Ws2_32.lib

Цитата

Еще несколько вопросов:
1. Что описывает класс HTTP_SendAns? Его функции вижу, а как это одним словом называется не пойму..
Класс отвечает за формирование ответа

Цитата

2. Что означает последний параметр в функции send_file_data(d,find_file_type(get_file_ext(fname)),false); ? 

Код

void HTTP_SendAns::send_file_data(string data, string type, bool dynamic)
Если dynamic заданно как true, то отправленные данные будут помеченны как только что измененные (через Last-Modified). Что отключит их кэширование в браузере и по дороге. Предназначенно для отправки динамически сгенерированных форм, которые потенциально могут выдывать разные страницы при каждом вызове
Цитата

3. Мой сайт построен так, что он состоит не из отдельных html страничек, а из php файлов, которые выдают информацию на страницу в зависимости от запросов пользователя. Используется довольно много Javascript и Ajax. 
Ой, на такое не расчитанно.
Цитата

В данном случае вместо php используется C++. Вопрос: место куда лучше вставить динамическую генерацию кода страничек 
Поддерживается .asp, очень обрезанный и только JacaScript. 
Занимается этим функция void send_asp(HTTP_SendAns &A, string s);, но она в эти исходники не входит. Поддержка JS довольно сильно переплетена с остальной частью программы, если надо, могу попробовать ее оторвать  smile 
Цитата

этоHTTP_SendAns::send_file1(string fname) ? 
Почти, это
Код

void WEB_Server::process_file(HTTP_SendAns &A, string fname)
{
 if (get_file_ext(fname)!=".asp") A.send_file(fname); else
  {
   string data=A.send_file1(fname);
   if (!data.empty()) send_asp(A,data);
  }
}
строки 5,6
Цитата

Т.к. там string d=find_resource("web\\"+fname); в переменной d, как я понял хранится код странички, которую сервер отошлет пользователю.
Да
Цитата

Получается здесь надо вставить мою функцию, которая будет динамически создавать сожержимое страницы. 
Да
Цитата

Но для генерации этого содержимого надо знать переменные POST и GET запросов, 
Угу, поле A.reg содержит HTTP_ReadReq, содержащий распарсенный запрос
Переменные и методы в нем:
Код

header_only - true, если пришел запрос HEAD, т.е. не нужно формировать тело страницы
get_hdr - Возвращает запись из заголовка HTTP запроса по ID 
get_cgi - Возвращает параметр из POST запроса и/или параметр из URL (после знака '?')
is_hdr_exist и is_cgi_exist - Проверяют наличие заданного параметра в заголовке HTTP и теле запроса соотвественно

Цитата

хорошо бы знать cookies для идентификации пользователя (как сессии в php) и хранения некоторых его переменных. 
Cookie придется реализовывать вручную, доступ к заголовкам запроса и ответа есть, так что Cookie (RFC2965) и Set-Cookie (RFC2109)

PM MAIL   Вверх
TheDestroyer
Дата 21.5.2009, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Спасибо за ответы. 
Удалось скомпилировать консольное приложение, поставив заглушки на недостающие функции, прилинковав Ws2_32.lib и создав главную функцию int _tmain(int argc, _TCHAR* argv[]) в web_server.cpp
Пытаюсь запустить сервер, делаю так:
Код

int _tmain(int argc, _TCHAR* argv[])
{
    web_server.do_init(80);
      // далее логично вызвать    
      // web_server.run();
      // но это частная переменная класса TCP_Server
    return 0;
}

Как правильно инициализировать и запустить веб сервер?

Функцию find_resource сделал такой, чтобы хоть что-то вывело клиенту:
Код

string find_resource(string name)
{
return "hello, <br> check";
}

Цитата(xvr @  21.5.2009,  12:24 Найти цитируемый пост)
Поддерживается .asp, очень обрезанный и только JacaScript. 

Как JavaScript поддерживается на стороне сервера?

PM MAIL   Вверх
xvr
Дата 21.5.2009, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(TheDestroyer @ 21.5.2009,  14:42)
Спасибо за ответы. 
Удалось скомпилировать консольное приложение, поставив заглушки на недостающие функции, прилинковав Ws2_32.lib и создав главную функцию int _tmain(int argc, _TCHAR* argv[]) в web_server.cpp
Пытаюсь запустить сервер, делаю так:
Код

int _tmain(int argc, _TCHAR* argv[])
{
    web_server.do_init(80);
      // далее логично вызвать    
      // web_server.run();
      // но это частная переменная класса TCP_Server
    return 0;
}

Как правильно инициализировать и запустить веб сервер?

web_server.do_init достаточно - он запускает run в нитке. (Макросы MAIN_FUNC и RUN_MAIN из StdAfx.h)
После do_init нужно повиснуть (например в for(;;) Sleep(1000);}. Или крутить цикл оконных сообщений, или что нибудь еще  smile 
Цитата


Функцию find_resource сделал такой, чтобы хоть что-то вывело клиенту:
Код

string find_resource(string name)
{
return "hello, <br> check";
}

Ок
Цитата

Цитата(xvr @  21.5.2009,  12:24 Найти цитируемый пост)
Поддерживается .asp, очень обрезанный и только JacaScript. 

Как JavaScript поддерживается на стороне сервера?
Используется встроенный в Windows интерпретатор JavaScript.
PM MAIL   Вверх
TheDestroyer
Дата 23.5.2009, 01:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Цитата(xvr @  21.5.2009,  15:04 Найти цитируемый пост)
Используется встроенный в Windows интерпретатор JavaScript. 

А что может делать JavaScript на стороне сервера?

Удалось получить тестовую строку на клиенте!
Код

Для этого в код перед созданием сокета пришлось добавить
 // инициализация WSAStartup (из MSDN)
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
 wVersionRequested = MAKEWORD(2, 2);
    err = WSAStartup(wVersionRequested, &wsaData);
    if (err != 0) {
        /* Tell the user that we could not find a usable */
        /* Winsock DLL.                                  */
        printf("WSAStartup failed with error: %d\n", err);
        return 1;
    }

 sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // создание сокета

Похоже, это та часть, которую надо будет менять для компиляции этого исходника под linux?

Разбираюсь с  переменными, которые  присылаются на сервер через GET и POST запросы.

Поставил такой html код на выдачу клиенту:
Код

string find_resource(string name)
{
string page="";
page = page+ 
"<html>\
 <head>\
  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1251\">\
  <title>Тег FORM</title>\
 </head>\
 <body>\
 <form action=\"/html/example/handler.php\">\
  <p><b>Как по вашему мнению расшифровывается аббревиатура &quot;ОС&quot;?</b></p>\
  <p><input type=\"radio\" name=\"answer\" value=\"a1\">Офицерский состав<Br>\
  <input type=\"radio\" name=\"answer\" value=\"a2\">Операционная система<Br>\
  <input type=\"radio\" name=\"answer\" value=\"a3\">Большой полосатый мух</p>\
  <p><input type=\"submit\"></p>\
 </form>\
 </body>\
</html>";
return page;

Не удается получить значения переменных param1, param2. Как их правильно получить? A.req.get_cgi не возвращает эти параметры. 
a1,a2 или a3 передаются в A.req.cgi_lines[1], т.е. все параметры с формы будут всегда в A.req.cgi_lines ?

PM MAIL   Вверх
xvr
Дата 23.5.2009, 09:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(TheDestroyer @ 23.5.2009,  01:33)
Цитата(xvr @  21.5.2009,  15:04 Найти цитируемый пост)
Используется встроенный в Windows интерпретатор JavaScript. 

А что может делать JavaScript на стороне сервера?

Формировать из .asp html  smile Обрабатывать он может что угодно. Для этого в глобальное пространство имен JS добавляются необходимые переменные, функции и объекты. Они собственно и обеспечивают весь функционал. Так же можно пользоваться любыми ActiveX контролами.

Цитата

Удалось получить тестовую строку на клиенте!
Для этого в код перед созданием сокета пришлось добавить
 // инициализация WSAStartup (из MSDN)
 
Угу, у моего сервера main выглядит так:
Код

extern "C" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int)
{
 setlocale( LC_ALL, ".ACP" );

 WSADATA dat;
 WSAStartup(MAKEWORD(2,0),&dat);
 CoInitializeEx(0,COINIT_MULTITHREADED);
 InitOrder::do_initialize();

 MSG msg;
 while(GetMessage(&msg,0,0,0)) DispatchMessage(&msg);

 InitOrder::do_terminate();
 CoUninitialize();
 WSACleanup();

 return 0;
}


Цитата

 sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // создание сокета
Это лишнее  smile 
Цитата

Похоже, это та часть, которую надо будет менять для компиляции этого исходника под linux?
Не только, в tcp_server.* есть некоторое количество функций WSA*, их надо будет заменить на эквивалентные из Linux. Так же там используется ожидание событий на сокете через Event'ы Windows. Linux этого не поддерживает. Придется делать либо неблокирующие сокеты либо ожидание через select/poll (или и то и другое)

Цитата

Разбираюсь с  переменными, которые  присылаются на сервер через GET и POST запросы.

Поставил такой html код на выдачу клиенту:
Код

string find_resource(string name)
{
string page="";
page = page+ 
"<html>\
 <head>\
  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1251\">\
  <title>Тег FORM</title>\
 </head>\
 <body>\
 <form action=\"/html/example/handler.php\">\
  <p><b>Как по вашему мнению расшифровывается аббревиатура &quot;ОС&quot;?</b></p>\
  <p><input type=\"radio\" name=\"answer\" value=\"a1\">Офицерский состав<Br>\
  <input type=\"radio\" name=\"answer\" value=\"a2\">Операционная система<Br>\
  <input type=\"radio\" name=\"answer\" value=\"a3\">Большой полосатый мух</p>\
  <p><input type=\"submit\"></p>\
 </form>\
 </body>\
</html>";
return page;

Не удается получить значения переменных param1, param2. 
А кто собственно такие param1 & parm2?
Цитата

Как их правильно получить? A.req.get_cgi не возвращает эти параметры. 
a1,a2 или a3 передаются в A.req.cgi_lines[1], т.е. все параметры с формы будут всегда в A.req.cgi_lines ?
Если в WEB браузере загрузить эту страницу, а потом сделать 'submit' ее на ваш сервер (я так понимаю это и делается), то в через get_cgi будет доступен параметр 'answer' со значением 'a1', 'a2' или 'a3', в зависимости от того, что выбрал пользователь на странице

PM MAIL   Вверх
TheDestroyer
Дата 24.5.2009, 19:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Цитата(xvr @  23.5.2009,  09:17 Найти цитируемый пост)
А кто собственно такие param1 & parm2?

Да, помимо опечатки, еще идея неверная была. Теперь клиенту отправляется это:
Код

page = page+ 
"<html>\
 <head>\
  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1251\">\
  <title>Тег FORM</title>\
 </head>\
 <body>\
 <form action=\"/html/example/handler.php?param1=123&param2=321\" method=\"post\">\
  <p><b>Как по вашему мнению расшифровывается аббревиатура &quot;ОС&quot;?</b></p>\
  <p><input type=\"radio\" name=\"answer\" value=\"a1\">Офицерский состав<Br>\
  <input type=\"radio\" name=\"answer\" value=\"a2\">Операционная система<Br>\
  <input type=\"radio\" name=\"answer\" value=\"a3\">Большой полосатый мух</p>\
  <p><input type=\"submit\"></p>\
 </form>\
 </body>\
</html>";

Пытаюсь через A.req.get_cgi получить значения переданных параметров:
В A.req.get_cgi(); надо передавать string id, а что это за id и как его получить? Если докопать до "корня" этой функции, то видно, что производится операция 
Код

map<string,string> cgi_lines;

 Похоже, что создается список в виде "параметр, значение".
Поясните, плз, что тут происходит и как правильно получить параметр 'answer' со значением 'a1', 'a2' или 'a3', в зависимости от того, что выбрал пользователь на странице. Или для получения параметров, переданных через GET запрос в адресе после знака "?" (handler.php?param1=123&param2=321). Также если параметров несколько , то хотелось бы получить их все в переменные (как в php). Похоже, что надо узнать сколько их через A.req.cgi_lines.size и в цикле for присвоить соответствующим переменным их значения? 
Получается все переданные параметры со своими значениями будут храниться в A.req.cgi_lines независимо от того, как они были приняты через POST или GET? (возможно передавть POST и GET одновременно некорректно...)



Это сообщение отредактировал(а) TheDestroyer - 24.5.2009, 19:39
PM MAIL   Вверх
xvr
Дата 24.5.2009, 22:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(TheDestroyer @ 24.5.2009,  19:35)
В A.req.get_cgi(); надо передавать string id, а что это за id и как его получить? 

Их надо знать. Предполагается, что вы сами формировали формы, которые клиент отправил вам, так что параметры вам должны быть известны
Цитата

Поясните, плз, что тут происходит и как правильно получить параметр 'answer' со значением 'a1', 'a2' или 'a3', в зависимости от того, что выбрал пользователь на странице. 
Собственно вызвать A.ret.get_cgi("answer"), оно вернет "a1", "a2" или "a3"
Цитата

Или для получения параметров, переданных через GET запрос в адресе после знака "?" (handler.php?param1=123&param2=321). 
И для них тоже
Цитата

Также если параметров несколько , то хотелось бы получить их все в переменные (как в php).
Такого интерфейса не предусмотрено, но его можно легко реализовать через обход A.req.cgi_lines (с помощью итератора)
Цитата

Получается все переданные параметры со своими значениями будут храниться в A.req.cgi_lines независимо от того, как они были приняты через POST или GET?
Да
Цитата

 (возможно передавть POST и GET одновременно некорректно...)
Одновременно и не получится - это типы одного и того же запроса. Но параметры после URL (через знак '?') вполне возможны и в POST запросе (хотя лучше этого не делать)

PM MAIL   Вверх
TheDestroyer
Дата 25.5.2009, 13:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Спасибо, с GET и POST ясно.
Разбираюсь с Cookies. Следуя 
Цитата(xvr @  21.5.2009,  12:24 Найти цитируемый пост)
Cookie (RFC2965) и Set-Cookie (RFC2109)

Делаю так:
для записи cookies пока для тестов в функции  string HTTP_SendAns::send_file1(string fname) ставлю:
Код

 // тест отправки cookies
 print_time(NULL,NULL,0,true);
 //add_hdr_line("Set-Cookie2: Customer=\"WILE_E_COYOTE\"; Version=\"1\"; Path=\"/acme\"; expires= %s",sout_lbuf.c_str());
 add_hdr_line("Set-Cookie: Customer=\"WILE_E_COYOTE\"; Version=\"1\"; Path=\"/acme\";");

в функции void WEB_Server::process_file(HTTP_SendAns &A, string fname)
Пишу:
Код

 string str2 = A.req.get_hdr("Cookie");

Хочу прочитать записанное, на форме из предыдущего примера жму Submit или просто обновляю страницу.
К сожалению, возвращается пустое значение. Смотрю в папке Cookies браузера (IE), созданных мной cookies там нет :(. Если заходить на данный веб сервер через FireFox, то в его cookies запись появляется. Но несмотря на это, считывание cookies при повторном заходе на страницу не происходит. Что тут может быть не так?
Возможно, в IE проблема с синтаксисом самой записи, может необходимо указывать  expires=...
Как правильно получить cookies?
Хорошо бы устанавливать время жизни cookies. Как получить текущее время + 30мин или +1 день с помощью функции  print_time() ?
Для записи cookies планирую сделать функцию в классе HTTP_SendAns: HTTP_SendAns::SetCookie(string item, string value).

Также, получать параметры переданные через GET и POST, записывать и читать cookies надо в функции динамического формирования странички. Сейчас это функция string find_resource(string name) в файле StdAfx.cpp. Как лучше сделать доступными A.req.get_cgi("..."), A.req.get_hdr("Cookies") и SetCookie(...) в find_resource()?

PM MAIL   Вверх
xvr
Дата 25.5.2009, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(TheDestroyer @ 25.5.2009,  13:11)
для записи cookies пока для тестов в функции  string HTTP_SendAns::send_file1(string fname) ставлю:
Код

 // тест отправки cookies
 print_time(NULL,NULL,0,true);
 add_hdr_line("Set-Cookie: Customer=\"WILE_E_COYOTE\"; Version=\"1\"; Path=\"/acme\";");

Хочу прочитать записанное, на форме из предыдущего примера жму Submit или просто обновляю страницу.
К сожалению, возвращается пустое значение. Смотрю в папке Cookies браузера (IE), созданных мной cookies там нет :(. 

Cookie привязываются к URL (точнее имени сервера), откуда была полученна страница. Возможно IE хочет увидеть этот URL где то явно (в записях заголовка или атрибуте Path), точно не знаю
Цитата

Возможно, в IE проблема с синтаксисом самой записи, может необходимо указывать  expires=...
Желательно
Цитата

Хорошо бы устанавливать время жизни cookies. Как получить текущее время + 30мин или +1 день с помощью функции  print_time() ?

Код

time_t tm=time(NULL)+30*60; // or 24*60*60
print_time("expires=","\r\n",tm);

Цитата

Также, получать параметры переданные через GET и POST, записывать и читать cookies надо в функции динамического формирования странички. 

Цитата

Сейчас это функция string find_resource(string name) в файле StdAfx.cpp. 
Нет, это функция получения содержимого. Все динамическое формирование должно происходить вне нее, базируясь на содержимом, которое она вернула.
А функция для формирования ответа, это WEB_Server::process_file, туда и надо вставлять генерацию динамического контента
Кроме того, есть специальная функция для обработки управляющих запросов -  WEB_Server::process_cmd (она сейчас пустая)

PM MAIL   Вверх
TheDestroyer
Дата 26.5.2009, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Пытаюсь динамически сгенерировать страницу. Делаю это так:
Код

void WEB_Server::process_file(HTTP_SendAns &A, string fname)
{
string page= ""; // содержимое отсылаемой страницы
string str1 = A.req.get_cgi("param1");
string str2 = A.req.get_hdr("Cookie");

 // тест отправки cookies
 time_t tm=time(NULL)+30*60; // + 30 мин or 24*60*60
 A.print_time(NULL,NULL,tm,true);
 A.add_hdr_line("Set-Cookie: Customer=\"WILE_E_COYOTE\"; Version=\"1\"; Path=\"/acme\"; expires= %s;",A.lbuf.c_str());
 // конец теста отправки cookies

page +=  
"<html>\
 <head>\
  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1251\">\
  <title>Тег FORM</title>\
 </head>\
 <body>\
 <form action=\"/html/example/handler.php?param1=123&param2=321\" method=\"post\">\
  <p><b>Как по вашему мнению расшифровывается аббревиатура &quot;ОС&quot;?</b></p>\
  <p><input type=\"radio\" name=\"answer\" value=\"a1\">Офицерский состав<Br>\
  <input type=\"radio\" name=\"answer\" value=\"a2\">Операционная система<Br>\
  <input type=\"radio\" name=\"answer\" value=\"a3\">Большой полосатый мух</p>\
  <p><input type=\"submit\"></p>\
 </form>\
 </body>\
</html>";

// отошлем содержимое
string d = page;
if (!d.empty()) A.send_file_data(d,find_file_type(get_file_ext(fname)),true);

Для проверки того, что получается при отправке и приеме сниффером (WireShark) проверяю запросы. Выявил странность: через браузер делаю запрос на сервер, сервер отвечает не одним пакетом, а двумя
сначала
Код

HTTP/1.1 200 OK
потом
Код

Server: MAC 1.0
Public: HEAD, PUT, GET
Date: Tue, 26 May 2009 07:54:45 GMT
Connection: close
Set-Cookie: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"; expires= Tue, 26 May 2009 08:24:44 GMT;
Last-Modified: Tue, 26 May 2009 07:54:45 GMT
Content-Length: 556
Content-Type: text/html; charset=cp1251

Проверил аналогичный запрос на сервер Apache, он отвечает одним пакетом
Код

HTTP/1.1 200 OK
Date: Tue, 26 May 2009 07:46:51 GMT
Server: Apache/2.2.8 (Win32) PHP/5.2.6
Last-Modified: Tue, 26 May 2009 07:46:27 GMT
ETag: "1e0000000641ff-24e-46acbec9ce4c5"
Accept-Ranges: bytes
Content-Length: 590
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

Возможно проблема с cookies из-за этого. 
UPDATE:
Нет, похоже это не проблема, да отсылка идет по частям, но это не влияет на процесс. 
Удалось передать cookies следующим образом:
Код

 A.add_hdr_line("Set-Cookie: Customer=test_customer; expires=%s;",A.lbuf.c_str());
 A.add_hdr_line("Set-Cookie: Test=testval; expires=%s;",A.lbuf.c_str());

А принять так:
Код

string str2 = A.req.get_hdr("Cookie");

В итоге в str2 строка со значениями через точку с запятой. Похоже остется разделить их в переменные или массив для дальнейшей работы с ними.
Для получения времени пришлось переместить функцию print_time в классе Http_SendAns из private в public

Это сообщение отредактировал(а) TheDestroyer - 26.5.2009, 13:34
PM MAIL   Вверх
xvr
Дата 26.5.2009, 18:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата

Для получения времени пришлось переместить функцию print_time в классе Http_SendAns из private в public
Лучше добавить в Http_SendAns метод для установки Cookie

PM MAIL   Вверх
TheDestroyer
Дата 26.5.2009, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Сделал установку и получение cookies. В итоге появились функции
Код

void HTTP_SendAns::SetCookie(string Item, string value, time_t exp_time)
{
string cookie="";
print_time(NULL,NULL,exp_time,true);
cookie = "Set-Cookie: "+Item+"="+value+"; "+"expires="+lbuf.c_str();
add_hdr_line(cookie.c_str());
}
void HTTP_ReadReq::get_cookies(string line)
{
 vector<string> cookie_vect; // массив строкового типа
 split(cookie_vect,line,';');
for(int i=0;i<cookie_vect.size();++i)
  {
   vector<string> s1;
   cookie_vect[i] = trim(cookie_vect[i]);
   split(s1,cookie_vect[i],'=',1);
   if (s1.empty()) continue;
   string key=transform(unescape_url(s1[0],true),tolower);
   if (key.empty()) continue;
   switch(s1.size())
   {
     case 1: cookie_lines[key]=""; break;
     case 2: cookie_lines[key]=unescape_url(s1[1],true); break;
    }
  } // for(int i=0;i<cookie_vect.size();++i)
}

class HTTP_ReadReq {
...
map<string,string> cookie_lines;
...
}; 

может пригодятся. Получать cookies точно также как и get_cgi или get_hdr.
В процессе добавления поддержки cookies выявил некорректную работу функции trim в StdAfx.cpp,  пришлось заменить
Код

if (p) s.erase(0,p-1);
на
if (p) s.erase(0,p);

Вроде теперь есть все инструменты для создания сайта. Но теперь встал вопрос о том, как добавить большие фрагменты JavaScript кода в фаил веб сервера. Просто вбивать их строковыми переменными явно неправильно. Хотелось бы просто загружать в строковую переменную содержимое .js файла и использовать ее. Как сделать так, чтобы JavaScript код был в отдельном .js файле для его удобного редактирования до комптляции и чтобы после компиляции все упаковывалось в один фаил? Такойже вопрос и с картинками для сайта.
PM MAIL   Вверх
xvr
Дата 26.5.2009, 22:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(TheDestroyer @ 26.5.2009,  21:37)
Сделал установку и получение cookies. В итоге появились функции

Спасибо, пригодится
Цитата

Но теперь встал вопрос о том, как добавить большие фрагменты JavaScript кода в фаил веб сервера. Такойже вопрос и с картинками для сайта.
Для этого была предназначенна функция find_resource. Она искала заданный файл по набору путей:
  •  Файл по пути из registry HKLM\Software\XVR\MACServer\1.0\Res (XVR\MACServer\1.0 надо заменить на что-нибудь свое)
  •  Во всех zip файлах по пути из registry HKLM\Software\XVR\MACServer\1.0\Res
  •  В папке data рядом с exe'ником
  •  Во всех zip файлах в этой папке
  •  В zip файле res-pack.zip рядом с exe'ником
  •  В zip файле, помещенном в ресурс RESPACK (типа RC_DATA) самого exe'ника
Файлы с реализацией в атаче

Чуть не забыл - для работы этой функции нужно прилинковать zlib


Это сообщение отредактировал(а) xvr - 26.5.2009, 22:54

Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  zipfile.zip 3,78 Kb
PM MAIL   Вверх
TheDestroyer
Дата 27.5.2009, 14:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Хотелось бы библиотеку zlib встроить в исполняемый фаил.
Скачал zlib1.2.3 c http://www.zlib.net/ (zlib source code, version 1.2.3, zipfile format)
Нашел инструкцию как скомпилировать zlib1.dll, а как встроить в exe-шник пока не могу найти. Если несложно, укажите, пожалуйста, как это сделать, ссылки на информацию или просто ключевые слова для поиска.
Также хотелось бы узнать о встраивании самих файлов с JavaScript кодом или других (возможно картинок) в спец. секцию исполняемого файла.
Вот что нашел по данной теме:
ссылка1, ссылка2, ссылка3
Получается после доставания из ресурсов фаил необходимо сохранить где-то. В приведенной Вами реализации, видимо, он сохраняется в оперативной памяти? 


Это сообщение отредактировал(а) TheDestroyer - 27.5.2009, 15:10
PM MAIL   Вверх
xvr
Дата 27.5.2009, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(TheDestroyer @ 27.5.2009,  14:41)
Хотелось бы библиотеку zlib встроить в исполняемый фаил.
Скачал zlib1.2.3 c http://www.zlib.net/ (zlib source code, version 1.2.3, zipfile format)
Нашел инструкцию как скомпилировать zlib1.dll, а как встроить в exe-шник пока не могу найти. 

Самый простой метод - взять все исходные файлы от zlib и добавить их в проект. Метод посложнее - сделать из них статическую библиотеку (в VS это специальный тип Win32 проекта - Static Library) и ее прилинковать к программе
Цитата

Также хотелось бы узнать о встраивании самих файлов с JavaScript кодом или других (возможно картинок) в спец. секцию исполняемого файла.
Пакуешь их все в zip архив (my_zip_archive.zip), в .rc файл проекта добавляешь 
Код

RESPACK RCDATA "my_zip_archive.zip"



Это сообщение отредактировал(а) xvr - 27.5.2009, 15:04
PM MAIL   Вверх
TheDestroyer
Дата 28.5.2009, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Удалось сделать статическую библиотеку и прилинковать ее к проекту.
Для этого пришлось сделать изменения в исходниках zlib (найдено в инете):
Код

movd mm4, [ESP +0] ==> movd mm4, DWORD PTR [ESP +0]
movd mm5,[esp+4]==>    movd mm5,dword ptr [esp+4]
movd mm7,[esi]==>    movd mm7,dword ptr [esi]
movd mm7,[esi]==> movd mm7,dword ptr [esi]

Также получилось засунуть zip фаил в ресурсы и достать из него текстовые файлы!
А как достать, например, картинку из этого zip архива, чтобы показать ее на страничке сайта?
Также хочется вынести функцию динамической генерации страничек в отдельную функцию в отдельном файле, т.к. она будет довольно большая. Т.е. сделать функцию void WEB_Server::web_process() {} в отдельном файле web_process.cpp. Делал так:
1. Создал фаил web_process.h в нем объявил WEB_Server::web_process(); , в web_process.cpp сделал #include "web_process.h". В web_process.h сделал #include "web_process.h". При компиляции вылетает куча ошибок о повторном определении функций и т.д.
2. Объявляю web_process() в web_server.h. Но надо как-то укзать что она находится в другом файле. Сответственно делаю в web_server.cpp #include "web_process.cpp". Но при компиляции вылезает ошибка, что в web_process.cpp WEB_Server: не является именем класса или пространства имен. Т.е. не видит класса WEB_Server.
Подскажите, плз, как вынести функцию void WEB_Server::web_process() {} в отдельный фаил.


PM MAIL   Вверх
xvr
Дата 28.5.2009, 12:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(TheDestroyer @ 28.5.2009,  12:31)
Также получилось засунуть zip фаил в ресурсы и достать из него текстовые файлы!
А как достать, например, картинку из этого zip архива, чтобы показать ее на страничке сайта?

Так же, как и текстовые. Файлы они и в африке файлы  smile 

Цитата

Также хочется вынести функцию динамической генерации страничек в отдельную функцию в отдельном файле, т.к. она будет довольно большая. Т.е. сделать функцию void WEB_Server::web_process() {} в отдельном файле web_process.cpp. Делал так:
1. Создал фаил web_process.h в нем объявил WEB_Server::web_process(); , в web_process.cpp сделал 
Ой.
Нужно в описании класса WEB_Server (в web_server.h) добавить вашу функцию web_process()
Ее тело можно расположить в отдельном файле (например в web_process.cpp)
В начале web_process.cpp надо сделать #include "web_server.h"

PM MAIL   Вверх
TheDestroyer
Дата 28.5.2009, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Цитата(xvr @  28.5.2009,  12:45 Найти цитируемый пост)
Нужно в описании класса WEB_Server (в web_server.h) добавить вашу функцию web_process()
Ее тело можно расположить в отдельном файле (например в web_process.cpp)
В начале web_process.cpp надо сделать #include "web_server.h"

Делаю так, но при компиляции в случае если прописать в web_process.cpp  #include "web_server.h" высыпает больше 100 синтаксических ошибок в файле tcp_server.h. Напомню, что в начале файла web_server.h стоит #include "tcp_server.h". Видимо надо прядок includ-ов как-то поменять.

Это сообщение отредактировал(а) TheDestroyer - 28.5.2009, 14:18
PM MAIL   Вверх
xvr
Дата 28.5.2009, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(TheDestroyer @ 28.5.2009,  14:11)
Делаю так, но при компиляции в случае если прописать в web_process.cpp  #include "web_server.h" высыпает больше 100 синтаксических ошибок в файле tcp_server.h. 

В самом начале web_process.cpp нужно написать #include "StdAfx.h" (самой первой строкой)
Цитата

Напомню, что в начале файла web_server.h стоит #include "tcp_server.h". Видимо надо прядок includ-ов как-то поменять.
Угу, StdAfx.h должен быть первый - в нем прописанны все include'ы и описания, общие для всех модулей.

PM MAIL   Вверх
TheDestroyer
Дата 28.5.2009, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Спасибо, получилось, правда пришлось перенести некоторые объявления из web_server.cpp в web_server.h.
Столкнулся с проблемой:
Есть моменты, когда необходимо передавать клиенту информацию несколько раз (или в цикле). Например, идет какой-то процесс и пишет свой лог, этот лог необходимо выдавать по мере его появления.
В php делал так:
Код

 while (!feof($pipes[1])) 
{
$pr_page = fgets($pipes[1], 1024);
$pr_page = str_replace("\n","<br>",$pr_page);
echo $pr_page;
flush();
}

Т.е. делал вывод в цикле, в браузер приходило все сразу как только появлялось в пайпе вывода.
Здесь же пробую делать так:
Код

string d = "CHECK!!!";
if (!d.empty()) A.send_file_data(d,find_file_type(get_file_ext(fname)),true);

d = "CHECK123!!!";
if (!d.empty()) A.send_file_data(d,find_file_type(get_file_ext(fname)),true);

В логе сервера появляется ошибка: Connection reset by network layer (11138616)
Видимо, сервер закрывает соединение сразу после отсылки информации. А как сделать вывод в браузер информации в реальном времени, на подобии примера на php?
PM MAIL   Вверх
azesmcar
Дата 28.5.2009, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(TheDestroyer @  28.5.2009,  15:14 Найти цитируемый пост)
Видимо, сервер закрывает соединение сразу после отсылки информации. А как сделать вывод в браузер информации в реальном времени, на подобии примера на php? 

а как идет вывод? через cout?
тогда
Код

std::cout << "something" << std::flush;

PM   Вверх
xvr
Дата 28.5.2009, 16:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(TheDestroyer @ 28.5.2009,  15:14)
Столкнулся с проблемой:
Есть моменты, когда необходимо передавать клиенту информацию несколько раз (или в цикле). Например, идет какой-то процесс и пишет свой лог, этот лог необходимо выдавать по мере его появления.

Здесь же пробую делать так:
Код

string d = "CHECK!!!";
if (!d.empty()) A.send_file_data(d,find_file_type(get_file_ext(fname)),true);

d = "CHECK123!!!";
if (!d.empty()) A.send_file_data(d,find_file_type(get_file_ext(fname)),true);

В логе сервера появляется ошибка: Connection reset by network layer (11138616)
Видимо, сервер закрывает соединение сразу после отсылки информации.

Угу. Система расчитанна на отправку данных одним куском. Она проставляет размер данных в соотвествующем поле заголовка (Content-Length) и закрывает соединение после отправки
Цитата

А как сделать вывод в браузер информации в реальном времени, на подобии примера на php?
Надо менять логику вывода. Она содержится в методе HTTP_SendAns::send_file_data
  •  Убрать поле Content-Length из заголовка (строка 387)
  •  Дописывать данные через метод HTTP_SendAns::write
Но это не очень чесный метод, для честного обновления страницы надо делать chunked передачу (в RFC расписанно)

PM MAIL   Вверх
TheDestroyer
Дата 1.6.2009, 20:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



С chunked пока не удалось реализовать частичную передачу, оставил вариант 
Цитата(xvr @  28.5.2009,  16:40 Найти цитируемый пост)
 Убрать поле Content-Length из заголовка (строка 387)
 Дописывать данные через метод HTTP_SendAns::write

Есть необходимость передавать на сервер файлы. Выдаю клиенту форму
Код

page ="<form method=post enctype='multipart/form-data'>"
"Укажите фаил: <br>"
"<input type='file' name='userfile' size=50 class=tbox><br>"
"<input type='submit' name=\"upload\" class='button' value='Upload'>"
"</form>";
if (!page.empty()) A.send_file_data(page,find_file_type(get_file_ext(fname)),true);

Как осуществить прием файлов?
PM MAIL   Вверх
xvr
Дата 1.6.2009, 22:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(TheDestroyer @ 1.6.2009,  20:39)
Как осуществить прием файлов?

Взять полновесный WEB сервер  smile При передаче файла включается передача как multipart/form-data, т.е. в принятом потоке надо делать полноценный MIME разбор. Включая поддержку multipart и всех transfer-encoding, которые захочет использовать сервер (хотя их можно и ограничить)
У меня где то были сорцы, которые этим занимались, но это еще столько же кода, сколько там уже есть  smile И я их вряд ли найду - уж очень давно это было

В общем смотреть RFC с описанием MIME кодирования

PM MAIL   Вверх
TheDestroyer
Дата 1.6.2009, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Да, уже копаю в сторону парсинга multipart/form-data. 
Нашел http://www.oreillynet.com/onjava/blog/2006...multiparts.html. 
http://pocoproject.org/download/, там много инструменов для работы с сетью (в частности class MultipartReader), но использование этой библиотеки означает, что появятся дополнительные файлы помимо исполняемого файла, и не хочется бросать то, что уже сделано, по идее остается добавить только парсинг multipart/form-data для закачки файлов на сервер. Если все-таки найдутся сорцы, то буду признателен.

Это сообщение отредактировал(а) TheDestroyer - 1.6.2009, 23:35
PM MAIL   Вверх
xvr
Дата 2.6.2009, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Увы, сорцы похоже канули в лету  smile Оторвите от библиотеки class MultipartReader и приделайте к себе, и никаких дополнительных файлов не надо

PM MAIL   Вверх
TheDestroyer
Дата 24.6.2009, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



С закачкой файлов пока не разобрался. Но появились вопросы:
1. Как указать кодировку в которой выдавать браузеру текст? Я использую JavaScript (XMLHttpRequest), при обращении к этой функции в браузере (IE) возникает ошибка ("Ошибка c00ce56e."), поиск показал, что используется неправильная кодировка. Для cp-1251 так?
Код

setlocale(LC_ALL,"Russian");

А как для UTF-8 ?
2. Проблема с редиректом. Использую функцию A.send_redir(redirect_url). В IE редирект проходит нормально, а в FireFox просто выдается весь текст страницы на белом фоне (т.е. воспринимается как plaintext). Посмотрел в FireBug в FireFox, там такая картина:
Код

<html>
<head/>
<body>
<pre><html><head> <style type="text/css">body { color: #000; font: 12px tahoma, verdana, arial, sans-serif; background-color: Gray; margin:0px; text-align:left;
...

т.е. получается, что head уже отправлен браузеру и все что я отправляю далее считается телом страницы (первые 3 строки FireFox вставил сам, отправленный мной текст начинается с "<html><head> <style type=...").
Как правильно делать редирект?


Это сообщение отредактировал(а) TheDestroyer - 24.6.2009, 18:12
PM MAIL   Вверх
xvr
Дата 24.6.2009, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Для указания кодировки используется поле заголовка Content-Type:, параметр charset=. Сервер автоматически выставлял CP1251 для текстовых файлов (см HTTP_SendAns::send_file_data)

Редирект можно делать специальными кодами возврата (30х) (см закоментареную часть в HTTP_SendAns::send_redir), но это не работало на некоторых проксях

Поэтому редирект делается через заголовок HTML страницы, META http-equiv Refresh. Т.е. редирект делается самим браузером путем немедленной перезагрузки страницы с другого URL

Цитата

Посмотрел в FireBug в FireFox, там такая картина:
А откуда взялся текст в странице? send_redir формирует пустую HTML страницу, у нее отлько служебное поле в заголовке HTML, больше ничего

PM MAIL   Вверх
TheDestroyer
Дата 29.6.2009, 00:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Сначала начал делать редирект сам, потом вспомнил, что видел уже это в коде, в итоге оставил как есть в HTTP_SendAns::send_redir, похоже это самый лучший вариант. Проблема была не в редиректе...
А вот проблему с IE и Ajax пока не решил. FF нормально работает, а IE постоянно выдает ошибку "Ошибка c00ce56e."
Похоже нашел решение: http://forum.vingrad.ru/forum/topic-237305...t-explorer.html с 4го поста снизу.
Идея в том, чтобы выдавать на аякс запрос в кодировке UTF-8. Как перекодировать отправляемый браузеру текст в эту кодировку? С помощью setlocale( LC_ALL, ... )?


Это сообщение отредактировал(а) TheDestroyer - 29.6.2009, 00:33
PM MAIL   Вверх
xvr
Дата 29.6.2009, 09:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(TheDestroyer @ 29.6.2009,  00:32)
Идея в том, чтобы выдавать на аякс запрос в кодировке UTF-8. Как перекодировать отправляемый браузеру текст в эту кодировку? 

Сервер отправляет содержимое строки 'как есть', никаких перекодировок не производится. Что бы это было UTF-8, исходная строка должна быть в UTF-8. Саму строку можно перекодировать чем угодно (например libiconv). Еще надо изменить кодировку в заголовке ответа (об этом уже писал)

Цитата

С помощью setlocale( LC_ALL, ... )?
Это не поможет. Он максимум может повлиять на cout, но никак не на внутренние самописные сервера  smile 
PM MAIL   Вверх
TheDestroyer
Дата 30.6.2009, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Спасибо за наводку на libiconv. Сделал чтобы сервер выдавал текст в UTF-8.
Возникла следующая проблема: если сервер обрабатывает запрос одного пользователя, то второй уже не может зайти на сайт (на данном сервере). Есть режим работы когда пользователю на страницу долго грузится результат работы некоторых приложений, в этом случае на сайт удается зайти только после того, как все операции будут закончены. Т.е. получается что вся работа с сокетом выполняется в одном потоке.
Код

#define RUN_MAIN(nm) _beginthread(&nm##_proxy,0,this)
...
RUN_MAIN(run);

run  - функция прослушивания сокета.
Как сделать так, чтобы каждому пользователю выделялся свой поток чтобы они могли работать одновременно?
Вот функция обработки сокета:
Код

void TCP_Server::run()
{// функция ожидания запросов от клиентов
 HANDLE h[]={sock_event,term_event};
 WSAEventSelect(sock,sock_event,FD_ACCEPT|FD_CLOSE);
 for(;;)
  {
   DWORD v=WaitForMultipleObjectsEx(2,h,FALSE,INFINITE,TRUE);
   switch(v)
    {
     case WAIT_OBJECT_0:
      {
       WSANETWORKEVENTS ne;
       WSAEnumNetworkEvents(sock,sock_event,&ne);
       if (ne.lNetworkEvents&FD_CLOSE) return;
       SOCKET s=accept(sock,NULL,NULL); // При появлении запроса от клиента accept успешно завершается, возвращая в переменной s дескриптор socket'а для обмена информацией с клиентом
       if (s==INVALID_SOCKET) continue;
       if (process_accept(s)) return; 
       break;
      }
     case WAIT_OBJECT_0+1: return;
     case WAIT_IO_COMPLETION: continue;
     default: error(2,"%s::run: Unexpected return value '%d' from WaitForMultipleObjectsEx",class_name,v);
    }
  }
}

Видимо, надо запускать поток для обработки process_accept(s) для каждого пользователя (а, наверное, правильнее говорить сеанса). Но тут проблема - в одном сеансе множество запросов (текст, картинки и т.д.). Как тут правильно поступить?

Также возник вопрос как запустить сервер на определенном адресе, если, например, у компьютера несколько сетевых карт?
PM MAIL   Вверх
xvr
Дата 30.6.2009, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Этот сервер намеренно был сделан single thread - для упрощения жизни (не надо связываться с синхронизацией обращений к серверным скриптам и данным для WEB страниц). Кроме того, специфика приложения - это был WEB интерфейс к программе (вместо GUI).
Если нужно многопоточное приложение, то поток надо заводить в методе WEB_Server::process_accept - все его содержимое запускать в потоке. Количество одновременно запущенных потоков можно (и даже нужно) ограничить - например сделать пул нитей, и отдавать запрос в нить из пула. По окончании обработки нить возвращать в пул.
Всю синхронизацию придется добавлять (например через критические секции)

Цитата

Также возник вопрос как запустить сервер на определенном адресе, если, например, у компьютера несколько сетевых карт? 
Никогда не пробовал. Видимо при bind'е исходного сокета нужно указать реальный адрес (сейчас используется константа INADDR_ANY - что означает - первый попавшийся)

Строка 13 в tcp_server.cpp:
Код

bool TCP_Server::do_init(int port) // return true on abort
{
 ...
 sockaddr_in sin;
 sin.sin_family = AF_INET;
 sin.sin_addr.s_addr = INADDR_ANY;  // <<<< Place real IP address here
 sin.sin_port = htons(port);
 if (bind(sock,(sockaddr*)&sin,sizeof(sin)))
 ...
}

PM MAIL   Вверх
TheDestroyer
Дата 30.6.2009, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Чтобы добавить многопоточность делаю так:
фаил tcp_server.cpp:
Код

void TCP_Server::run()
{// функция ожидания запросов от клиентов
 HANDLE h[]={sock_event,term_event};
 WSAEventSelect(sock,sock_event,FD_ACCEPT|FD_CLOSE);
 for(;;)
  {
   DWORD v=WaitForMultipleObjectsEx(2,h,FALSE,INFINITE,TRUE);
   switch(v)
    {
     case WAIT_OBJECT_0:
      {
       WSANETWORKEVENTS ne;
       WSAEnumNetworkEvents(sock,sock_event,&ne);
       if (ne.lNetworkEvents&FD_CLOSE) return;
       SOCKET s=accept(sock,NULL,NULL); // При появлении запроса от клиента accept успешно завершается, возвращая в переменной s дескриптор socket'а для обмена информацией с клиентом
       if (s==INVALID_SOCKET) continue;
       if (process_accept(s)) return; 
      //RUN_MAIN(process_accept);// <<<
     _beginthread(WEB_Server::process_accept_m, 0, (void*) s); // <<<
       break;
      }
     case WAIT_OBJECT_0+1: return;
     case WAIT_IO_COMPLETION: continue;
     default: error(2,"%s::run: Unexpected return value '%d' from WaitForMultipleObjectsEx",class_name,v);
    }
  }
}

Пытался запустить поток аналогично потоку с обработкой сокета (через RUN_MAIN), но вылезают ошибки о неправильных объявлениях... Тогда решил работать с  _beginthread напрямую. 
К сожалению просто так в функцию, передаваемую в  _beginthread параметры не передашь. Да еще эта функция должна быть типа void и иметь параметр типа (void *param) .
Примеры смотрел здесь:
http://msdn.microsoft.com/en-us/library/kdzttdcb(VS.71).aspx
http://www.rsdn.ru/forum/cpp/4612.flat.aspx
http://www.gamedev.net/community/forums/to...topic_id=448462
В борланде было проще - указал на запуск функции в отдельном потоке и все функции которые вызываются из нее тоже запускаются в том потоке, и все без преобразования типов передаваемых параметров и т.д. Может и тут так можно?

Пришлось сдеделать static функции:
фаил web_server.h:
Код

public:
...
 static void process_accept_m(void *sv);
 static void process_file_m(HTTP_SendAns&, string fname);
 static void process_root_m(HTTP_SendAns &a) {process_file_m(a,"index.html");}
 static void process_cmd_m(HTTP_SendAns&, string cmd);

фаил web_server.cpp - добавил функции с _m на конце (multithread) аналогичные их оригиналам. Только, наверное, прийдется им передавать параметры также как и в static void process_accept_m(void *sv). Пока до этого не дошел.
Код

void WEB_Server::process_cmd_m(HTTP_SendAns &A, string cmd)
{
}

void WEB_Server::process_file_m(HTTP_SendAns &A, string fname)
{
Web_pages web_page;
string page= ""; // содержимое отсылаемой страницы
if ((fname == "process.php") || (fname == "index.html"))
{// если фаил динамических страниц
web_process(A, fname);
}
else
{// все остальное просто подгружаем из файлов
A.send_file(fname);
}

void WEB_Server::process_accept_m(void *sv)
{
 SOCKET s = SOCKET(sv);
 HTTP_ReadReq req(s); // объявляем переменную req типа HTTP_ReadReq, заполняем структуру req (расшифруем запрос)
 if (req.load_req()) return;
 HTTP_SendAns ans(&req); // заполняем структуру ans
 string url=req.get_url(); // получим запрашиваемый клиентом URL
 if (url.empty() || url=="/") process_root_m(ans); else  // если запрос корневой директории, то выдадим index.html
  {
   if (url[0]=='/') url.erase(0,1);
   if (url[0]=='$') {url.erase(0,1); process_cmd_m(ans,url);}
   else process_file_m(ans,url); // если не команда и не корневая директория, то выдадим запрашиваемый фаил
  }
}

При компиляции ругается на то, что 
Код

web_server.cpp(39) : error C2352: WEB_Server::web_process: недопустимый вызов нестатической функции-члена

Здесь это строка 11.
Неужели прийдется делать все вызываемые далее функции статическими? Может у меня неправильный подход?
Далее, критическими секциями, видимо, прийдется защитить, переменные которые используются в программе глобально?

Это сообщение отредактировал(а) TheDestroyer - 30.6.2009, 20:17
PM MAIL   Вверх
xvr
Дата 30.6.2009, 21:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Подход в корне не верный. Обработку надо делать в коде WEB_Server::process_accept

Например так

Код


class WEB_Server : public InitOrder , public TCP_Server {
 // Add some members and types
 struct RunInfo {
   SOCKET s;
   WEB_Server* self;
   RunInfo(SOCKET s1, WEB_Server* sl) :s(s1), self(sl) {}
 };
 
 void process_accept_imp(SOCKET s);
 static void __cdecl process_accept_imp_proxy(void *p) 
  {
   RunInfo* ri = (RunInfo*)p;
   ri->self->process_accept_imp(ri->s);
   delete ri;
  }

};

bool WEB_Server::process_accept(SOCKET s)
{
 _beginthread(&process_accept_imp_proxy,0,new RunInfo(s,this));
 return false;
}

// Rename old WEB_Server::process_accept into WEB_Server::process_accept_imp


Далее - все обращения из бывшего WEB_Server::process_accept к общим ресурсам (в первую очередь - поиск и загрузка файлов) должны быть защищены критическими секциями

Далее - эта реализация будет создавать по отдельному thread'у на каждый запрос. При большом числе запросов сервер может помереть  smile 
PM MAIL   Вверх
TheDestroyer
Дата 1.7.2009, 00:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



Класс, я замучался с этими потоками. Спасибо огромное.
Если несложно пояснить:
здесь добавлена структура RunInfo, в ней есть RunInfo(SOCKET s1, WEB_Server* sl) :s(s1), self(sl) {}. Это инициализация структуры? Похоже на конструктор.

По поводу защиты критическими секциями. Видимо при запросе от клиента все сводится к функции void WEB_Server::process_file(HTTP_SendAns &A, string fname). А там либо генерация кода страницы, либо подгрузка файлов из ресурсов.
Достаточно ли защитить подгрузку файлов следующим образом:
фаил web_server.cpp:
Код

...
CRITICAL_SECTION cs;
bool WEB_Server::process_accept(SOCKET s)
{
InitializeCriticalSection( &cs ); 
_beginthread(&process_accept_imp_proxy,0,new RunInfo(s,this));
 return false;
}

фаил zipfile.cpp:
Код

string find_resource(string name)
{
string res;
EnterCriticalSection( &cs );
res = get_rs().find_resource(name);
LeaveCriticalSection( &cs );
 return res;
}

Пример с критическими секциями смотрел здесь: http://www.cyberguru.ru/programming/cpp/mu...ntro-page2.html
В find_resource будут защищены все переменные что во вложенном в нее вызове функции или только одна переменная res?
Где лучше объявить CRITICAL_SECTION cs чтобы использовать в файлах zipfile.cpp и web_server.cpp?
PM MAIL   Вверх
xvr
Дата 1.7.2009, 11:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(TheDestroyer @ 1.7.2009,  00:05)
Класс, я замучался с этими потоками. Спасибо огромное.
Если несложно пояснить:
здесь добавлена структура RunInfo, в ней есть RunInfo(SOCKET s1, WEB_Server* sl) :s(s1), self(sl) {}. Это инициализация структуры? Похоже на конструктор.

В С++ структуры и классы - это одно и то же (отличается только спицификатор доступа по умолчанию - для структуры public, для класса - private). Так что это конструктор и есть

Цитата

Достаточно ли защитить подгрузку файлов следующим образом:

InitializeCriticalSection( &cs ); нужно вынести из WEB_Server::process_accept и поместить куда то на самый верхний уровень - ее нужно вызвать ТОЛЬКО 1 раз до первого использования самой критической секции

Цитата

В find_resource будут защищены все переменные что во вложенном в нее вызове функции или только одна переменная res?
Все.

Цитата

Где лучше объявить CRITICAL_SECTION cs чтобы использовать в файлах zipfile.cpp и web_server.cpp?
Где нибудь в zipfile.cpp. В web_server.cpp ее вообще заносить не надо. Можно сделать так:
(фаил zipfile.cpp):
Код

static CRITICAL_SECTION* get_cs()
{
 static CRITICAL_SECTION cs;
 InitializeCriticalSection(&cs);
 return &cs;
}

string find_resource(string name)
{
 static CRITICAL_SECTION* cs=get_cs(); // <<< 'static' here is a 'must' word! Do not remove it!

 string res;
 EnterCriticalSection( cs );
 res = get_rs().find_resource(name);
 LeaveCriticalSection( cs );
 return res;
}

PM MAIL   Вверх
TheDestroyer
Дата 5.7.2009, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 112
Регистрация: 5.11.2007

Репутация: нет
Всего: нет



С многопоточностью вроде разобрался, спасибо.
Обнаружилась проблема: если я передаю GET методом на веб сервер строку типа "qwe%20-qwe%20+qwe", то пропадает знак "+". Стал разбираться, обнаружил:
Код

static string unescape_url(string url, bool supp_plus)
{
 string dst;
 const char* p=url.c_str();
 int len=url.size();
 dst.reserve(len);
 for(;len--;++p)
  switch(*(unsigned char*)p)
   {
    case '%': if (len<2) return dst;
              {char c=x2c(p+1); dst.append(&c,1);}
              p+=2; len-=2; break;
    case '+': if (supp_plus) {dst+=" "; break;}
    default:  dst.append(p,1); break;
   }
 return dst;
}

Чем грозит переключение supp_plus в false? Как правильно обработать этот момент?
PM MAIL   Вверх
xvr
Дата 5.7.2009, 21:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



При кодировании URL пробелы заменяются на знак '+' (HTTP требует). Если нужен пробел лучше передавать его как %31


PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1228 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.