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 ☆☆☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.