PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Программирование на PureBasic в Linux » Web-приложение.


Web-приложение.

Сообщений 1 страница 15 из 15

1

Здравствуйте, у меня есть приложение написанное на PureBasic и скомпилированное под Linux, мне нужно из него сделать web-приложение, чтобы человек зайдя на сайт видел на этом сайте интерфейс ввода и вывода программы, ну и соответственно смог воспользоваться этим приложением прямо там на сайте. У меня два вопроса:
1. Есть ли какие либо программы, которые переводят Linux-приложение в Web-приложение автоматически? Ну что то вроде, открыл программу, загрузил в неё приложение и страничку в инете, где нужно разместить.
2. Вот что мне посоветовали на одном форуме PHP:

переделать приложение до пригодного в скриптах.
Самый простой метод - принимать параметры запуска и выводить в stdout результат. exec и компания
Либо сокеты - переделать приложение для работы по сети и из PHP сокетами обращаться. fsockopen в базовом случае.

У меня всё вводится  и выводится через EditorGadjet, то есть соответственно через GetGadgetText() и SetGadgetText(), вот у меня вопрос поддерживают ли эти функции (раз они кросплатформенные) STDIN/STDOUT? Если нет, то как это можно прописать?

0

2

HTML знаешь?
Можно изменить программу так, чтобы она работала как веб сервер, генерируя веб-странички, которые будут отображаться в браузере.
Простейший пример http://purebasic.mybb.ru/viewtopic.php?id=149

0

3

Пётр, HTML не знаю, но уже приступаю осваивать. Я просмотрел код, более и менее разобрался, но не понял несколько строк. Не мог бы ты прокомментировать каждую из них (то что понял, я прокомментировал):

Из процедуры Generate_HTML_Code():

Код:
HTML_Code=""
HTML_Code+"<html><head><title>"+#ProgName+"</title>";отображени во вкладке
HTML_Code+"<STYLE TYPE="+Chr(34)+"text/css"+Chr(34)+"><!—BODY {background-color: black; font-family: Verdana; color: white; font-size: 9px} —> </STYLE>"
HTML_Code+"<meta http-equiv="+Chr(34)+"Content-Type"+Chr(34)+" content="+Chr(34)+"text/html; Charset=windows-1251"+Chr(34)
HTML_Code+"<META HTTP-EQUIV="+Chr(34)+"Refresh"+Chr(34)+" CONTENT="+Chr(34)+"2;URL="+Chr(34)+">"
HTML_Code+"</head><body><b>USB термометр</b>"+StatusSensor;то что термометр подключен
If DeviceHandle;если соеденение есть, тогда выводим температуру
   HTML_Code+"</br><b>Текущая температура  - <span style="+Chr(34)+"font-weight: bold>; color: rgb(0, 102, 0);"+Chr(34)+">"+StrF(CurrentThermo,1)+"  °C  </span></b><br>"
EndIf
HTML_Code+"</body></html>"

Из процедуры Server_Event(*xx):

Код:
ReceiveNetworkData(ClientID, *Buffer, 10000);идёт приём данных от клиента
SendNetworkString(ClientID, "HTTP/1.0 200 OK"+Chr($0D)+Chr($0A))
SendNetworkString(ClientID, "Server: "+#ProgName+Chr($0D)+Chr($0A))
SendNetworkString(ClientID, "Content-Length: "+Str(Len_HTML)+Chr($0D)+Chr($0A))
SendNetworkString(ClientID, "Content-Type: text/html"+Chr($0D)+Chr($0A))
SendNetworkString(ClientID, Chr($0D)+Chr($0A))
SendNetworkString(ClientID, OutHTML);отсылаем клиету сгенерированную web-страничку (строку)

И есть ещё вопрос, если брать не постоянное генерирование странички, а уже созданную web-страничку, где расположены кнопки, textbox и с неё принимать входные данные (у меня это текст, то есть одна строковая переменная) и отсылать обработанные данные (тоже в данном случаи строка) как это примерно сделать? Или же того же самого можно добится и с помощью генерирования странички?

0

4

goodwen написал(а):

Из процедуры Generate_HTML_Code():

Это генерация HTML кода странички.

goodwen написал(а):

Из процедуры Server_Event(*xx):

Это заголовок ответа, необходимый для браузера.

0

5

Пётр написал(а):

Это заголовок ответа, необходимый для браузера.

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

Отредактировано goodwen (25.04.2011 21:11:01)

0

6

Это служебная информация для браузера - заголовок ответа.
Читай вики, там про это написано. http://ru.wikipedia.org/wiki/HTTP
Когда хоть немного ознакомишься с HTML, то такие вопросы сами пропадут.

0

7

Пётр, у меня вот такой вопрос, взял процедуры Server_Event(*xx), вот к примеру, человек 5 работают практически одновременно с приложением через web-форму, данные приходят ко мне на сервер, а там эти данные уже обрабатывает приложение и отсылает обратно клиенту, но вот такой сервер путать не будет что кому посылать? Я имею ввиду ещё не был до конца обработаны данные для одного клиента, а уже пришли новые данные от другого клиента. Нужно ли здесь какие нибудь мьютексы использовать для взаимодействия? Или же это уже в функциях библиотеки network предусмотрено?

А так же вот такой вопрос, мне в качестве входных данных приходит текст, приложение его обрабатывает и отсылает клиенту, что он обработан и результат обработки хранится в массиве, после чего клиент вводит вопрос, который приходит в качестве входных данных, приложение его обрабатывает и отсылает ответ по вопросы. Вот сам вопрос: если у нас несколько пользователей одновременно работают с приложением, каждый отослал текст и для каждого результат обработки его текста сохранён временно в массиве (но массив один), вот будет ли путоница, или же внутри функций библиотеки network уже предусмотрено, чтобы данные обрабатывались последовательно? Если нет, то как можно исправить данную проблему?

0

8

goodwen написал(а):

Пётр, у меня вот такой вопрос, взял процедуры Server_Event(*xx), вот к примеру, человек 5 работают практически одновременно с приложением через web-форму, данные приходят ко мне на сервер, а там эти данные уже обрабатывает приложение и отсылает обратно клиенту, но вот такой сервер путать не будет что кому посылать?

Если все правильно сделать то путать не будет.
Когда поступает запрос серверу, то функция EventClient() возвращает уникальный идентификатор клиента, запросившего данные. Если отсылать данные, используя именно этот идентификатор, то данные попадут требуемому клиенту, даже если в один и тот же момент времени, идет обмен данными с несколькими клиентами.
Смотри как это сделано в Web-сервере.

Код:
Procedure ServerRoot(*bool)
  Shared *Buffer
  Protected AnalystRequest.AnalystRequest
  Repeat
    SEvent = NetworkServerEvent()
    If SEvent
      ClientID = EventClient()
         Select SEvent
           Case #PB_NetworkEvent_Connect ; Новый клиент подключился к серверу
             
           Case #PB_NetworkEvent_Data    ; От клинета пришли данные
             For m=0 To 10008 Step 4
               PokeL(*Buffer+m, 0)
             Next m
             CountBytes=ReceiveNetworkData(ClientID, *Buffer, 10000)
             
             If CountBytes>=0
               AnalystRequest\buffer = *Buffer
               AnalystRequest\SizeBuf = CountBytes
               AnalystRequest\ClientID = ClientID
                If CreateThread(@Analyst_request(), @AnalystRequest) = 0 ; Данные для клиента если не получилось создать поток.
                    SendNetworkString(ClientID, "HTTP/1.1 200 OK"+Chr($0D)+Chr($0A))
                    SendNetworkString(ClientID, GenerateCurrentDate()+Chr($0D)+Chr($0A))
                    SendNetworkString(ClientID, "Server: "+#ProgName+Chr($0D)+Chr($0A))
                    SendNetworkString(ClientID, "Content-Length: "+Str(Len(#Overload)+2)+Chr($0D)+Chr($0A))
                    SendNetworkString(ClientID, "Content-Type: text/html"+Chr($0D)+Chr($0A))
                    SendNetworkString(ClientID, Chr($0D)+Chr($0A))
                    SendNetworkString(ClientID, #Overload)
                    SendNetworkString(ClientID, Chr($0D)+Chr($0A))
                Else
                    Delay(20)
                EndIf
             EndIf
             
           Case #PB_NetworkEvent_File    ; От клиента пришел файл
             
           Case #PB_NetworkEvent_Disconnect  ; Клиент разорвал соединение с сервером
             
         EndSelect      
    Else
      Delay(20)
    EndIf
  ForEver
EndProcedure

Обрати внимание что перед созданием параллельного потока, данные помещаются в структуру, указатель на которую передается процедуре, работающей в потоке.
Среди этих данных, есть переменная ClientID, хранящая идентификатор клиента, т. е. созданный поток будет отсылать данные только клиенту, которому они предназначены.

goodwen написал(а):

Нужно ли здесь какие нибудь мьютексы использовать для взаимодействия?

Сложно сказать не видя кода.
В примере веб сервера (может одновременно работать с несколькими сотнями клиентов), мьютексы не использовались, а каждый запрос, обрабатывался в отдельном потоке.

goodwen написал(а):

Вот сам вопрос: если у нас несколько пользователей одновременно работают с приложением, каждый отослал текст и для каждого результат обработки его текста сохранён временно в массиве (но массив один)

Опять-же не видя кода, сложно ответить.
Ведь если массив локальный, то это не один и тот же массив, а разные!
Но лучше хранить данные в динамически связанном списке, добавляя элемент при коннекте клиента и уничтожая его при дисконекте.
Динамический список можен содержать в себе массивы.
Хотя можно использовать и ассоциативные массивы (Map).

0

9

Пётр, я код предоставить не могу, поскольку он очень здоровый, но там всё по процедурам разбито, то есть дефрагментация текста в одной процедуре, анализ текста в другой, запись результата в тот массив (который является глобальным) в ещё одной процедуре, анализ вопроса и поиск ответа в другой процедуре и затем в обработчике событий использую эти процедуры, вот я хочу использовать их примерно так же поставив как показано в коде:

Код:
Procedure Server_Event(*x) ; Отдельный поток, в котором обрабатываются Web-сервером запросы от браузеров.
  Shared *Buffer
  
  Repeat;начало цикла
    SEvent = NetworkServerEvent();информация полученная от сервера
    If SEvent
      ClientID = EventClient();получение ID клиента
         Select SEvent
           Case #PB_NetworkEvent_Connect ; Новый клиент подключился к серверу
             
           Case #PB_NetworkEvent_Data    ; От клинета пришли данные
                    
             ReceiveNetworkData(ClientID, *Buffer, 10000);идёт приём данных от клиента

                               ; и вот здесь прописать по порядку эти функции                

             SendNetworkString(ClientID, "HTTP/1.0 200 OK"+Chr($0D)+Chr($0A))
             SendNetworkString(ClientID, "Server: "+#ProgName+Chr($0D)+Chr($0A))
             SendNetworkString(ClientID, "Content-Length: "+Str(Len_HTML)+Chr($0D)+Chr($0A))
             SendNetworkString(ClientID, "Content-Type: text/html"+Chr($0D)+Chr($0A))
             SendNetworkString(ClientID, Chr($0D)+Chr($0A))

             SendNetworkString(ClientID, OutHTML); и здесь соответственно отправлять ответ на вопрос
             
           Case #PB_NetworkEvent_File    ; От клиента пришел файл
             
           Case #PB_NetworkEvent_Disconnect  ; Клиент разорвал соединение с сервером
             
         EndSelect      
    Else;если информация не пришла
      Delay(20);приостановить программу на 20 милисекунд
    EndIf
  ForEver;конец цикла
EndProcedure

Вот в таком случаи, на твой взгляд, нужны мьютексы?

Пётр написал(а):

Но лучше хранить данные в динамически связанном списке, добавляя элемент при коннекте клиента и уничтожая его при дисконекте.
Динамический список можен содержать в себе массивы.

Пытался сейчас найти, как это сделать и не нашёл, ты имел в виду через структуру? (пример ниже)

Код:
Structure mas
  Dim result_mas.s(0); он затем увеличивается по мере записи
EndStructure

NewList klients_result_mas.mas()
AddElement(klients_result_mas())
klients_result_mas()\result_mas(s4et_result_mas) = ....
Пётр написал(а):

Хотя можно использовать и ассоциативные массивы (Map).

И где про них можно почитать?

Отредактировано goodwen (05.05.2011 00:05:09)

0

10

goodwen написал(а):

запись результата в тот массив (который является глобальным)

Если глобальный, то программа сможет в один и тот же момент времени работать только с одним клиентом.

goodwen написал(а):

; и вот здесь прописать по порядку эти функции

Это из кода Procedure Server_Event(*x)
Что там будет?
В таком виде как сейчас, он не многопоточный, а однопоточный - обрабатывает одного клиента за другим, а не одновременно.

goodwen написал(а):

Пытался сейчас найти, как это сделать и не нашёл, ты имел в виду через структуру? (пример ниже)

Ну примерно.

Код:
Structure mas
  Array result_mas.s(10); он затем увеличивается по мере записи
EndStructure

NewList klients_result_mas.mas()
AddElement(klients_result_mas())
goodwen написал(а):

И где про них можно почитать?

В справке. в разделе Map.

0

11

Пётр написал(а):

Это из кода Procedure Server_Event(*x)
Что там будет?
В таком виде как сейчас, он не многопоточный, а однопоточный - обрабатывает одного клиента за другим, а не одновременно.

Мне приходит на ум только так: объявить процедуру  и в ней уже используются все мои процедуры для анализа. и вот она уже запускается на том месте в отдельном потоке, то есть будет одна строка:

Код:
CreateThread(@obwaia_procedura(), ClientID)

А перед этим соответственно добавление нового элемента в список и использование массива в этом элементе в новом потоке для клиента.

В таком виде он будет многопоточным, или лучше по другому организовать?

Отредактировано goodwen (05.05.2011 00:37:29)

0

12

goodwen написал(а):

А перед этим соответственно добавление нового элемента в список и использование массива в этом элементе в новом потоке для клиента.

Должно быть многопоточным, точнее работать сразу с несколькими клиентами.

0

13

Пётр, вот черновик приблизительный:

Код:
Structure mas
  ClientIDtable.l
  Array result_mas.s(10); он затем увеличивается по мере записи
EndStructure

NewList klients_result_mas.mas() ; объявление структурированного списка для доступа к массиву хранения Знаний, Прогнозов и Версий

Procedure Server_Event(*x) ; Отдельный поток, в котором обрабатываются Web-сервером запросы от браузеров.
  Shared *Buffer
  
  Repeat;начало цикла
    SEvent = NetworkServerEvent();информация полученная от сервера
    If SEvent
      ClientID = EventClient();получение ID клиента
         Select SEvent
           Case #PB_NetworkEvent_Connect ; Новый клиент подключился к серверу
             
           Case #PB_NetworkEvent_Data    ; От клинета пришли данные
             
             start=#True;
             ReceiveNetworkData(ClientID, *Buffer, 10000);мидёт приём данных от клиента
             
             ForEach; перебираем цикл, чтобы узнать есть ли для этого клиента уже массив с результатами
                     ; ведь ещё приходят вопросы, ответы на которые ищутся в этом массиве
               If ClientID = klients_result_mas()\ClientIDtable; если соответственно равен то сразу запускаем процедуру
                 CreateThread(@procedura(),ClientID); запуску процедуры для отдельного клиента
                 start=#False; это для следующего условия
               EndIf  
             Next
             
             If start=#True; если переменная будет false, то не будет заводится массив для того клиента, у которого уже есть массив с результатами
               AddElement(klients_result_mas()); новая таблица, для нового клиента
               CreateThread(@procedura(),ClientID); запуску процедуры для отдельного клиента 
             EndIf  

             SendNetworkString(ClientID, "HTTP/1.0 200 OK"+Chr($0D)+Chr($0A))
             SendNetworkString(ClientID, "Server: "+#ProgName+Chr($0D)+Chr($0A))
             SendNetworkString(ClientID, "Content-Length: "+Str(Len_HTML)+Chr($0D)+Chr($0A))
             SendNetworkString(ClientID, "Content-Type: text/html"+Chr($0D)+Chr($0A))
             SendNetworkString(ClientID, Chr($0D)+Chr($0A))
             
             SendNetworkString(ClientID, OutHTML); отсылаем клиету найденный ответ
             
           Case #PB_NetworkEvent_File    ; От клиента пришел файл
             
           Case #PB_NetworkEvent_Disconnect  ; Клиент разорвал соединение с сервером
             
             ; и здесь удаление из списка того массива, который соответствовал номеру клиенту
             
         EndSelect      
    Else;если информация не пришла
      Delay(20);приостановить программу на 20 милисекунд
    EndIf
  ForEver;конец цикла
EndProcedure

Мне только не нравиться использование start=#False, а как можно без этого обойтись? Да и будет ли он примерно такой организации работать сразу с несколькими клиентами?

0

14

А зачем создавать элемент при приходе пакета данных?
Ведь по логике вещей, это нужно делать при подключении клиента

Код:
 Structure mas
  ClientIDtable.l
  Array result_mas.s(10); он затем увеличивается по мере записи
EndStructure

NewList klients_result_mas.mas() ; объявление структурированного списка для доступа к массиву хранения Знаний, Прогнозов и Версий

Procedure Server_Event(*x) ; Отдельный поток, в котором обрабатываются Web-сервером запросы от браузеров.
  Shared *Buffer, klients_result_mas()
  
  Repeat;начало цикла
    SEvent = NetworkServerEvent();информация полученная от сервера
    If SEvent
      ClientID = EventClient();получение ID клиента
         Select SEvent
           Case #PB_NetworkEvent_Connect ; Новый клиент подключился к серверу
             
             AddElement(klients_result_mas()); новая таблица, для нового клиента
             klients_result_mas()\ClientIDtable = ClientID
             
           Case #PB_NetworkEvent_Data    ; От клинета пришли данные
             
             ; Это еужно производить в потоке обсдуживания клиента
             ;ReceiveNetworkData(ClientID, *Buffer, 10000); идёт приём данных от клиента
             
             CreateThread(@procedura(), ClientID); запуску процедуры для отдельного клиента
             
             
             ; Ответ нужно формировать в потоке, когда обработаны данные
             
;              If start=#True; если переменная будет false, то не будет заводится массив для того клиента, у которого уже есть массив с результатами
;                AddElement(klients_result_mas()); новая таблица, для нового клиента
;                CreateThread(@procedura(),ClientID); запуску процедуры для отдельного клиента 
;              EndIf  
;              
;              SendNetworkString(ClientID, "HTTP/1.0 200 OK"+Chr($0D)+Chr($0A))
;              SendNetworkString(ClientID, "Server: "+#ProgName+Chr($0D)+Chr($0A))
;              SendNetworkString(ClientID, "Content-Length: "+Str(Len_HTML)+Chr($0D)+Chr($0A))
;              SendNetworkString(ClientID, "Content-Type: text/html"+Chr($0D)+Chr($0A))
;              SendNetworkString(ClientID, Chr($0D)+Chr($0A))
;              
;              SendNetworkString(ClientID, OutHTML); отсылаем клиету найденный ответ
             
           Case #PB_NetworkEvent_File    ; От клиента пришел файл
             
           Case #PB_NetworkEvent_Disconnect  ; Клиент разорвал соединение с сервером
             
              ; и здесь удаление из списка того массива, который соответствовал номеру клиенту
             ForEach klients_result_mas()
               If klients_result_mas()\ClientIDtable = ClientID
                 DeleteElement(klients_result_mas())
                 Break
               EndIf
             Next 
             
         EndSelect      
    Else;если информация не пришла
      Delay(20);приостановить программу на 20 милисекунд
    EndIf
  ForEver;конец цикла
EndProcedure

0

15

Пётр, спасибо за помощь.

0


Вы здесь » PureBasic - форум » Программирование на PureBasic в Linux » Web-приложение.