LINUX.ORG.RU

TCP - сервер на Gambas. Большие задержки в методе ServerSocket.Accept

 , , ,


0

1

Проблема заключается в том что строка 49 содержащая

NewSocket = ServerTCP.Accept() 
обрабатывается неприемлемо долгое время, бывает до 4х секунд. Мне подсказывали что надо выносить приём соединения в отдельный поток и я даже придумал как это сделать. Но это не элегантный метод, а скорее нагромождение костылей. Как можно ускорить приём соединений или штатными средствами Gambas (пусть и с использованием библиотек на других языках) вынести приём соединений в отдельный поток?

Пока что я придумал просто запустить много процессов при старте, установить с ними соединения через локальные сокеты заранее и переводить по очереди их в слушающее состояние. Но как вы уже поняли, это плохо по многим причинам - не идеально в общем. Требуется минимум 100 соединений, а желательно 1000. Поскольку я это делаю для сетевой игры, то вполне возможна такая ситуация когда в течении небольшого времени к игре будет подключаться несколько клиентов, что будет означать задержки в передаче данных другим игрокам.

Стартовая процедура

Public Sub Main()
  Dim s As New TcpServerClass
  'tcpServerModule.Main()
  s.Port = 19000
  s.Listen()
  Do
    s.DoEvents(0.02) ' эквивалент Wait 0.02
  Loop
End

Класс TcpServerClass https://gist.github.com/anonymous/6bc31b7baf0cabfe380b

' Gambas class file

Public Const DefaultPort As Integer = 2100

Private ServerTCP As ServerSocket ' для принятия новых соединений
Private NewSocket As Socket '
Private PoolSocet As New Socket[]
Private TimeConnect As Single

Public Port As Integer

Public Sub _new()
  Port = DefaultPort
End


Public Sub Listen(Optional MaxConn As Integer = 0)
  'Port = 19000
  If ServerTCP = Null Then
    'Сокет пустой
  Else
    'Сокет не пустой
    ServerTCP.Close ' закрыть таки
    ServerTCP = Null ' уничтожить
  Endif
  ServerTCP = New ServerSocket ' создать сокет
  Object.Attach(ServerTCP, Me, "ServerTCP") ' присвоить имя для принятия событий
    
  ServerTCP.Port = Port ' установить порт для прослушивания
  ServerTCP.Listen(MaxConn) ' начать слушать
End

Public Sub DoEvents(s As Single)
  ' Рекомендую для linux значение s = 0.02
  Do
    Wait s
  Loop
End


Public Sub ServerTCP_Connection(RemoteHostIP As String)
  Dim t As Single
  'If TimeConnect = 0 Then TimeConnect = Timer
  'If ServerTCP.Count > 40 Then Print Str(Timer - TimeConnect)
  
  Print "Соединение принято " & Str(ServerTCP.Count)
  
  t = Timer
    NewSocket = ServerTCP.Accept()
  Print Str(Timer - t)
  
  'Print "RemotePort " & Str(NewSocket.RemotePort)
  'Print "LocalPort  " & Str(NewSocket.LocalPort)
End

Программа выдаёт следующие результаты:

Соединение принято 0
3,407837357372E-5
Соединение принято 1
4,1055958718061E-5
Соединение принято 2
2,6928493753076E-5
Соединение принято 3
2,7052126824856E-5
Соединение принято 4
2,797250635922E-5
Соединение принято 5
2,5926856324077E-5
Соединение принято 6
2,8021051548421E-5
Соединение принято 7
2,7173431590199E-5
Соединение принято 8
4,3035368435085E-5
Соединение принято 9
2,5833956897259E-5
Соединение принято 10
1,6867532394826E-5
Соединение принято 11
2,8021051548421E-5
Соединение принято 12
2,6874826289713E-5
Соединение принято 13
2,6974477805197E-5
Соединение принято 14
2,8138048946857E-5
Соединение принято 15
2,7765287086368E-5
Соединение принято 16
3,9785169064999E-5
Соединение принято 17
2,116768155247E-5
Соединение принято 18
2,7392990887165E-5
Соединение принято 19
2,7542584575713E-5
Соединение принято 20
2,7177622541785E-5
Соединение принято 21
2,8249341994524E-5
Соединение принято 22
2,725119702518E-5
Соединение принято 23
2,887228038162E-5
Соединение принято 24
4,0733604691923E-5
Соединение принято 25
2,8465059585869E-5
Соединение принято 26
2,9125600121915E-5
Соединение принято 27
2,8362963348627E-5
Соединение принято 28
2,685165964067E-5
Соединение принято 29
2,8569716960192E-5
Соединение принято 30
2,910930197686E-5
Соединение принято 31
2,7992413379252E-5
Соединение принято 32
2,7461908757687E-5
Соединение принято 33
4,2687286622822E-5
Соединение принято 34
2,8032925911248E-5
Соединение принято 35
2,8243171982467E-5
Соединение принято 36
2,6990543119609E-5
Соединение принято 37
2,84364214167E-5
Соединение принято 38
2,8283800929785E-5
Соединение принято 39
2,7270289137959E-5
Соединение принято 40
2,7500209398568E-5
Соединение принято 41
5,0343805924058E-5
Соединение принято 42
2,9171933420002E-5
Соединение принято 43
2,8057605959475E-5
Соединение принято 44
2,7992413379252E-5
Соединение принято 45
4,5635504648089E-5
Соединение принято 46
2,8613489121199E-5
Соединение принято 47
2,9823044314981E-5
Соединение принято 48
2,8844573535025E-5
Соединение принято 49
2,8726411983371E-5
Соединение принято 50
4,0744314901531E-5
Соединение принято 51
2,9611983336508E-5
Соединение принято 52
2,8617680072784E-5
Соединение принято 53
2,9698945581913E-5
Соединение принято 54
2,8582406230271E-5
Соединение принято 55
0,00021411373746
Соединение принято 0
3,0475319363177E-5



Последнее исправление: rezedent12 (всего исправлений: 1)

Но 3,407837357372E-5 например, - это же 0,0000340783. Где тут секунды?

anonymous
()

Узнал ТС по четвёртому слову в заголовке.

И сразу же вопрос: почему ты выбрал Gambas? И что говорит на этот счёт официальный мёртвый форум: http://gambas.pro/forum/ ?

EXL ☕☕☕☕☕
()

Тогда ТС возьми Мармелад и не мучайся. Там всё на Lua, но можно и на си++ писать :D

menangen
()

брось каку, изучай С лучше

Harald
()
Ответ на: комментарий от EXL

И сразу же вопрос: почему ты выбрал Gambas?

Личное предпочтение. «Вкусы».

И что говорит на этот счёт официальный мёртвый форум: http://gambas.pro/forum/ ?

Я туда часто задаю вопросы и иногда даже выкладываю разработанные мною компоненты.

rezedent12
() автор топика
Ответ на: комментарий от EXL

Хуже. Это язык программирования напоминающий Basic так же, как Delphi напоминает Pascal.

Это диалект basic немного похожий на java.

rezedent12
() автор топика

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

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

Pinkbyte 👍
()
Ответ на: комментарий от Pinkbyte

то есть я подозреваю что GUI там нет...

Его там нет.

rezedent12
() автор топика

Почему ты игноришь первый ответ, и до сих пор не удалил топик, чтоб никто это позорище не видел?

bj
()
Ответ на: комментарий от bj

Почему ты игноришь первый ответ, и до сих пор не удалил топик, чтоб никто это позорище не видел?

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

rezedent12
() автор топика
Ответ на: комментарий от bj

Где в своем выхлопе увидел секунды?

Я видел большие задержки в выводе строк.

Что такое E-5, знаешь?

Конечно же нет.

rezedent12
() автор топика
Ответ на: комментарий от rezedent12

Конечно же нет.

Это мантисса, E-5 = 10 в минус пятой степени. Кстати bj возможно прав - можеи тормозит не сетевой стек, а тормозит(или буферизируется) вывод на экран

Pinkbyte 👍
()
Ответ на: комментарий от Pinkbyte

можеи тормозит не сетевой стек, а тормозит(или буферизируется) вывод на экран

Хм.. проведу другие тесты.

rezedent12
() автор топика
Ответ на: комментарий от Pinkbyte

Дело как я понял не в сетевом стеке, а всё таки в преобразованиях во время вывода данных. Так как «по умолчанию» преобразования видимо не оптимальны. Однако если явно задать формат вывода, то код выполняется очень быстро.

Public Sub ServerTCP_Connection(RemoteHostIP As String)
  Dim t As Single, t1 As Single, t2 As Single
  Print "Соединение принято " & Str(ServerTCP.Count) & "    ";
  t1 = Timer
    NewSocket = ServerTCP.Accept()
  t2 = Timer
  Print Format((t2 - t1), "#.#########")
End

Выдал результаты:

Соединение принято 0     ,000030994
Соединение принято 1     ,000026941
Соединение принято 2     ,000026941
Соединение принято 3     ,000026941
Соединение принято 4     ,000025034
Соединение принято 5     ,000039101
Соединение принято 6     ,000010967
Соединение принято 7     ,00000906
Соединение принято 8     ,00000906
Соединение принято 9     ,000008821
Соединение принято 10     ,000010014

Установка множества соединений была осуществлена следующим кодом:

Public ClientSocket As New Socket[]
Public tmpSocket As Socket

Public Sub Main()
  Dim a As Integer
  Dim r As String
  For a = 0 To 60
    'открытие
    tmpSocket = New Socket
    ClientSocket.Add(tmpSocket, a)
    ClientSocket[a].Connect("127.0.0.1", 19000)
    Print "Открыто " & Str(a)
  Next

  Wait 10 ' пауза 10 секунд, во время ожидания так же происходит обработка событий
     
  For a = 0 To 60
    'закрытие
    ClientSocket[a].Close
    Print "Закрыто " & Str(a)
  Next
  
End

rezedent12
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.