forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   PureBasic (http://forum.boolean.name/forumdisplay.php?f=90)
-   -   Пример сервера на PureBasic (http://forum.boolean.name/showthread.php?t=17617)

DStalk 12.12.2012 17:33

Пример сервера на PureBasic
 
Вложений: 1
Пока допиливаю свои ммо-поделки, решил поделиться небольшими наработками по серверу на пурике.:)

В общем, сервер, работает в трех потоках, использует БД SQLite. В аттаче архив с иходниками и exe сервера, а также тестового клиента.

Основной поток (MainLoop) обрабатывает принятые пакеты, формирует пакеты на отправку через два списка. Второй поток добавляет принятые сервером данные в первый список, а третий поток считывает данные из второго списка и отправляет нужным клиентам.
Код сдобрен комментами, так что проблем возникнуть не должно.

Проверить работу можно через тест-клиент, который написан на блитце. При старте клиент сразу сам подключается к серверу на порт 9105 (выдаст MAV, если сервер не запущен или недоступен). Он работает в "ручном" режиме - то есть нужно набирать пакет с клавиатуры. Формат пакета: "[Команда]#[Данные]#...#[Данные]#", Где # - разделитель Chr(13) - добавляется по клавише F1 клиента. Enter - отправить пакет.

Команды:
Login#Name#Pass#version#
Register#Name#Pass#version#e-mail#
Move#X#Y#

Каждую команду обрабатывает отдельная процедура, то есть легко добавить на сервер новые команды.

В общем, может кому-то пригодится:) Также просьба похаять код, подсказать что можно улучшить/переделать - например формат и метод обработки пакетов.


DarkInside 13.12.2012 09:12

Ответ: Пример сервера на PureBasic
 
Автору респект:super: не каждый день такое выкладывают. Давно хотел разобраться в серверной части, буду учиться на примере твоего кода. По коду ничего сказать не могу, ибо ничерта не смыслю в серверах, но хотел бы сказать отдельное спасибо за качественные комменты, буду разбираться на досуге:)

Devilox 27.10.2013 00:06

Ответ: Пример сервера на PureBasic
 
А как соединяться? Он работает только для своего компа, а с другим компом даже через hamachi не удалось соединиться :dontknow:

DStalk 27.10.2013 11:01

Ответ: Пример сервера на PureBasic
 
Возможно порт закрыт? Ограничений то нет никаких, в клиенте просто вместо localhost нужно указать ip-адрес, где сервер крутится.

Devilox 27.10.2013 11:47

Ответ: Пример сервера на PureBasic
 
Спасибо! Работает :)

Devilox 27.10.2013 16:53

Ответ: Пример сервера на PureBasic
 
В коде есть переменные tmpData и tmpSpecial. Что такое tmp? А то я уже начинаю путаться.

DStalk 27.10.2013 17:50

Ответ: Пример сервера на PureBasic
 
tmp - temp, временная переменная:) я просто их так обозвал.
Сразу после считывания данных из очереди (Queue), элемент списка очереди удаляется (чтобы не держать mutex заблокированным), а данные из него сохраняются как раз во временных переменных и далее обрабатываются.

Devilox 27.10.2013 20:02

Ответ: Пример сервера на PureBasic
 
Обязательно ли использовать базу данных, или можно записывать в простой текстовый файл?

DStalk 27.10.2013 20:47

Ответ: Пример сервера на PureBasic
 
Конечно можно - база данных нужна для более быстрого поиска, выборки по определенным полям и т.п., в общем оптимальней...

Devilox 27.10.2013 21:45

Ответ: Пример сервера на PureBasic
 
Интересно, Delay(10) в данном коде значительно ускоряет программу. С чем это связано?
Код:

If CreateNetworkServer(Ip,Port)
  PrintN("The server has been created!")
 
  If CreateThread(@ReceiveTCPdata(),0) = 1
    PrintN("The receive thread has been started!")
  Else
    PrintN("The receive thread failed!")
    Delay(2000)
    End
  EndIf

  Repeat
    If TrySemaphore(SemaphoreIn) <> 0
      LockMutex(MutexIn)
      FirstElement(QueueIn())
      TempFlag.i = QueueIn()\Flag
      TCPclientID = QueueIn()\TCPclientID
      TempData.s = QueueIn()\TCPdata
      UnlockMutex(MutexIn)
      DeleteElement(QueueIn())
 
      Select TempFlag
        Case 1;Новое подключение
          connectMap(Str(TCPclientID))\Packet=""
          PrintN("New connection: "+Str(TCPclientID))
        Case 2;Дисконнект
          PrintN("Disconnected: "+Str(TCPclientID))
          DeleteMapElement(ConnectMap(),Str(TCPclientID))
      EndSelect
    EndIf 
   
    Delay(10)
   
  Until Inkey() = Chr(27)

  CloseNetworkServer(Ip)
 
Else
  PrintN("The server creation failed!")
  Delay(2000)
  End
EndIf


SBJoker 27.10.2013 22:05

Ответ: Пример сервера на PureBasic
 
В потенциально бесконечных циклах, без delay произойдёт явление похожее на зависание, когда программа будет потреблять 100% процессорных ресурсов. В результате система может неиметь достаточных ресурсов чтобы выполнить свою часть работы, результатов работы которйо программа и ожидает таким способом.

Посути команда Delay(10) даёт немного времени системе для выполнения своих дел. Хотя я бы в таком цикле поставил время отдаваемое системе побольше, например 100.

impersonalis 27.10.2013 23:26

Ответ: Пример сервера на PureBasic
 
Кроме того, если получение данных от сетевого интерфейса идёт в другом потоке, то такая спин-блокировка (отсутствие delay на одноядерном камне) может привести к ситуации дефицита ресурсов процессора для задачи получения данных, что в итоге отобразится на основном потоке, который с этими данными и работает (по сути, Джокер это и написал).

Пётр 28.10.2013 01:53

Ответ: Пример сервера на PureBasic
 
В коде есть несколько потенциальных "глючных" мест.
Цитата:

If CreateThread(@ReceiveTCPdata(),0) = 1
С чего вдруг функции CreateThread() возвращать 1?
В справке ясно написано.
Цитата:

Возвращаемое значение.
Номер созданного потока, или ноль если новый поток создать невозможно. Этот номер необходим, если вы хотите контролировать поток с помощью других функций этой библиотеки.
Номер потока не обязательно равен числу 1. В итоге даже при успешном создании потока, прога завершится с сообщением об ошибке.

Цитата:

UnlockMutex(MutexIn)
DeleteElement(QueueIn())
Почему сначала расблокируется мьютекс, а затем удаляется элемент? Должно быть наоборот. Иначе возможна ситуация что будет удален не тот элемент, если другой поток обратится в списку и изменит текущий элемент.

Devilox 28.10.2013 07:02

Ответ: Пример сервера на PureBasic
 
Спасибо, учту :)

Devilox 30.10.2013 20:36

Ответ: Пример сервера на PureBasic
 
Каким образом мы используем ASCII коды 31 и 10, и как они оказываются в пакетах, принятых от клиента?


Часовой пояс GMT +4, время: 18:04.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot