PureBasic - форум

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

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


Вы здесь » PureBasic - форум » PureBasic для Windows » Простой network server


Простой network server

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

1

Тема для меня новая, так что могу глупить в очевидных вещах.
Вообщем, задумал я с сайта переслать некоторые данные на другой сервер, там их обработать и вернуть. Как обычно, ничего не получилось. Тогда решил сделать задачу менее глобальной.
Поднял на локальной машине Wamp-server и кое-как насобирал скудную инфу(как мне показалось) по сетевым подключениям в PB. В итоге, я кое-как написал сетевой сервер, вот он, голубчик:

Код:
EnableExplicit

Define ServerPort.i = 8081
Define ClientID.i
Define *Buffer
Define Response$

Procedure.s ProcessData(Data$)
  ; Здесь буду обрабатывать полученные данные
  ProcedureReturn UCase(Data$) ; а пока просто буду возвращать все в верхнем регистре
EndProcedure

OpenConsole()
PrintN("Server started on port " + Str(ServerPort))

*Buffer = AllocateMemory(65536) ; Выделяем память здесь, 65536- максимально возможный буфер

If CreateNetworkServer(15, ServerPort)
  PrintN("Network server created successfully.")
  Repeat
    ClientID = NetworkServerEvent(15)
    If ClientID > 0
      Select ClientID
        Case #PB_NetworkEvent_Data
          If *Buffer
            If ReceiveNetworkData(ClientID, *Buffer, 65536) > 0 ; <--- вот тут лезет Invalid memory access (read error at address 2) при попытке заслать данные на сервер
              PokeB(*Buffer + 65536, 0) ; Null-terminate the string
              Response$ = PeekS(*Buffer, -1, #PB_UTF8)
              PrintN("Received: " + Response$)
              
              Response$ = ProcessData(Response$)
              
              SendNetworkString(ClientID, "HTTP/1.1 200 OK" + #CRLF$)
              SendNetworkString(ClientID, "Content-Type: text/plain" + #CRLF$)
              SendNetworkString(ClientID, "Content-Length: " + Str(Len(Response$)) + #CRLF$ + #CRLF$)
              SendNetworkString(ClientID, Response$)
            EndIf
          Else
            PrintN("Failed to allocate memory.")
          EndIf
          
        Case #PB_NetworkEvent_Disconnect
          PrintN("Client disconnected: " + Str(ClientID))
      EndSelect
    EndIf
  ForEver
Else
  PrintN("Failed to create server.")
EndIf

FreeMemory(*Buffer) 
CloseConsole()

Сервер запускается, я пытаюсь проверить его, набирая в браузере (при запущенном Wamp) http://127.0.0.1:8081/ и моментально мой сервер падает с ошибкой, что в строке
If ReceiveNetworkData(ClientID, *Buffer, 65536) > 0
Invalid memory access (read error at address 2)

Что у меня не так?
Вместо port 8081 ставил наобум 6500, эффект тот же.

Отредактировано Goga (25.07.2024 17:29:41)

0

2

В функциях ReceiveNetworkData() и SendNetworkString() нужно использовать результат вызова функции Connection=EventClient(), а не результат от NetworkServerEvent()
Ну, и InitNetwork() почему-то в коде не было.

Этот код ниже работает без выдачи сообщения об ошибке.
В нем в примечаниях к строкам словами ";- добавил" и ";- исправил" я пометил те строки, где я изменил исходный код программы.
Остальное не изменял.

Код:
EnableExplicit

Define ServerPort.i = 8081
Define ClientID.i
Define *Buffer
Define Response$
Define Connection.l   ;- добавил

Procedure.s ProcessData(Data$)
  ; Здесь буду обрабатывать полученные данные
  ProcedureReturn UCase(Data$) ; а пока просто буду возвращать все в верхнем регистре
EndProcedure

InitNetwork()  ;- добавил
OpenConsole()
PrintN("Server started on port " + Str(ServerPort))

*Buffer = AllocateMemory(65536) ; Выделяем память здесь, 65536- максимально возможный буфер

If CreateNetworkServer(15, ServerPort)
  PrintN("Network server created successfully.")
  Repeat
    ClientID = NetworkServerEvent(15)
    If ClientID > 0
      Select ClientID
        Case #PB_NetworkEvent_Data
          Connection = EventClient() ;- добавил
          If *Buffer
            If ReceiveNetworkData(Connection, *Buffer, 65536) > 0 ;- исправил на Connection <--- вот тут лезет Invalid memory access (read error at address 2) при попытке заслать данные на сервер
              PokeB(*Buffer + 65536, 0) ; Null-terminate the string
              Response$ = PeekS(*Buffer, -1, #PB_UTF8)
              PrintN("Received: " + Response$)
              
              Response$ = ProcessData(Response$)
              
              SendNetworkString(Connection, "HTTP/1.1 200 OK" + #CRLF$) ;- исправил на Connection 
              SendNetworkString(Connection, "Content-Type: text/plain" + #CRLF$) ;- исправил на Connection 
              SendNetworkString(Connection, "Content-Length: " + Str(Len(Response$)) + #CRLF$ + #CRLF$) ;- исправил на Connection 
              SendNetworkString(Connection, Response$) ;- исправил на Connection 
            EndIf
          Else
            PrintN("Failed to allocate memory.")
          EndIf
          
        Case #PB_NetworkEvent_Disconnect
          PrintN("Client disconnected: " + Str(Connection))
      EndSelect
    EndIf
  ForEver
Else
  PrintN("Failed to create server.")
EndIf

FreeMemory(*Buffer) 
CloseConsole()

Отредактировано Nemo3001 (26.07.2024 01:42:14)

0

3

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

PokeB(*Buffer + 65536, 0) ; Null-terminate the string

Запустите этот код с включенным purifier.

Код:
PurifierGranularity(#PB_Ignore, #PB_Ignore, #PB_Ignore, 2)
*Buffer = AllocateMemory(65536)
PokeB(*Buffer + 65536, 0) ; Null-terminate the string
End

0

4

Nemo3001,
InitNetwork(), видимо, в версии 6.11 не требуется указывать отдельно, видимо, библиотеку встроили (давно пора).
В том виде, в котором вы предложили свой код на замену моим потугам, все равно не работал, вылетала та же ошибка, но с другим адресом памяти. Однако, спасибо за наводку, используя ваше замечание я получил полностью рабочий код на локальной машине:

Код:

EnableExplicit

Define ServerPort = 8081
Define ClientID
Define *Buffer
Define Response$

Procedure.s ProcessData(Data$)
  ; Здесь буду обрабатывать полученные данные
  ProcedureReturn UCase(Data$) ; а пока просто буду возвращать все в верхнем регистре
EndProcedure

OpenConsole()
PrintN("Server started on port " + Str(ServerPort))

If CreateNetworkServer(15, ServerPort)
  Repeat
    Select NetworkServerEvent(15)
      Case #PB_NetworkEvent_Data
        ClientID = EventClient()
        *Buffer = AllocateMemory(65536)
        If *Buffer
          If ReceiveNetworkData(ClientID, *Buffer, 65536) > 0
            Response$ = PeekS(*Buffer, -1, #PB_UTF8)
            PrintN("Received: " + Response$)
            
            Response$ = ProcessData(Response$)
            
            SendNetworkString(ClientID, "HTTP/1.1 200 OK" + #CRLF$)
            SendNetworkString(ClientID, "Content-Type: text/plain" + #CRLF$)
            SendNetworkString(ClientID, "Content-Length: " + Str(Len(Response$)) + #CRLF$ + #CRLF$)
            SendNetworkString(ClientID, Response$)
          EndIf
          FreeMemory(*Buffer)
        Else
          PrintN("Failed to allocate memory.")
        EndIf
        
      Case #PB_NetworkEvent_Disconnect
        ClientID = EventClient()
        PrintN("Client disconnected: " + Str(ClientID))
    EndSelect
  ForEver
Else
  PrintN("Failed to create server.")
EndIf

CloseConsole()

Отредактировано Goga (26.07.2024 13:44:39)

0

5

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

Запустите этот код с включенным purifier.

К своему стыду я даже и не знал о PurifierGranularity() и purifier  :dontknow:
Я вообще выкинул PokeB(*Buffer + 65536, 0) , но хотел бы понять вашу идею с этим пьюрифиер. Если вам не сложно, можете объяснить?

0

6

Goga
идея в том что к указателю прибавлено 65536, по сути вы вставите байт за пределами выделенной памяти. Сам ни разу не пользовался пурифаер, но прочитал, что он вставляет метки вокруг выделенной памяти и если они будут перезаписаны, то он выдаст вам это как ошибку записи за пределами выделенной памяти.

Чтобы легче понять запишем код

Код:
*Buffer = AllocateMemory(1)
PokeB(*Buffer + 1, 0)

выделили 1 байт, его адрес *Buffer, если мы запишем в этот адрес, то мы запишем именно в этот выделенный байт. Если бы добавим +1, то выделенный байт окажется "сзади за курсором" если курсор это наш адрес, а значит последняя позиция в выделенной памяти на единицу меньше чем выделенная память, если складывать адрес и выделенную память.

Отредактировано AZJIO (26.07.2024 14:56:46)

0

7

Спасибо, Azjio, за объяснение.
Технология интересная для дебагга и любителей ковыряния в памяти) 
Надо как-нибудь с ней познакомиться по-ближе.

0

8

Goga
посмотри в справке про AllocateMemory(), там по русски написано, выделенная память забивается нулями
PokeB(*Buffer + XXX, 0) так что не имеет смысла

0


Вы здесь » PureBasic - форум » PureBasic для Windows » Простой network server