Что нового

Долгая обработка TCPRecv

La2Angel

Новичок
Сообщения
156
Репутация
1
Доброго времени суток, вообщем назрел такой вопрос. Есть 2 пк, написал сервер для своих нужд, подключается порядка 100 машин. Дак вот, функция
Код:
TCPRecv($ConnectedSocket[$i][0],65535)
работает и быстро обрабатывает входящие соединения и скрипт не думает на 1 машине, на другой же машине, скрипт получает данные долго и тормозит.
Нашел некоторое решение, делать.
Код:
Opt('TCPTimeout', 10)
Вот тогда на второй машине начинает работать нормально. В чем может быть проблема ? Ведь если таймаут оставить по стандарту, то значительно скорость снижается только на 1 машине.
 
Автор
L

La2Angel

Новичок
Сообщения
156
Репутация
1
Нет до думок, из-за чего такое может происходить?
 

InnI

AutoIT Гуру
Сообщения
4,951
Репутация
1,446
La2Angel
из-за чего такое может происходить?
Давайте думать вместе. Функция TCPRecv() получает данные за время, указанное в TCPTimeout.
Вызываем функцию. Функция начинает получать данные. Как только она получила все данные - количество символов, указанное вторым параметром - она сразу завершает работу. Если она не получила указанное количество символов за время TCPTimeout, то её работа будет завершена принудительно. Следовательно, у вас либо не все данные приходят, либо данные не приходят вообще, либо функция после получения всех данных всё равно продолжает работать до окончания времени TCPTimeout.
Измерьте время работы функции и проанализируйте полученные данные.
Возможно проблема связана с сетевыми драйверами. Попробуйте переустановить драйвера сетевой карты.
 
Автор
L

La2Angel

Новичок
Сообщения
156
Репутация
1
То же думал, что с драйверами проблема, не решили вопрос и ОС другую поставил. Вопрос-то мучает, на 1 ПК нормально все, на 2 ПК тормозит с одинаковыми характеристиками и нагрузкой.
 
Автор
L

La2Angel

Новичок
Сообщения
156
Репутация
1
Вообщем по времени не понятная муть, скрипт исполняется в цикле.
ПК1:
1. Запуск сервера
2. Пошел прием данных
3. Реагирует на нажатия клавиатуры и кнопку закрытия программы нормально.
ПК2:
1. Запуск сервера
2. Пошел прием данных (В чем интерес, пока нет клиентов, работает отлично)
3. После подключения клиентов, реагирует на клавиатуру долго и закрытие программы происходит долго.
НО есть большое но! Если сделать NotifyBox, то он быстро высвечивает сообщение, т.е. цикл не останавливается и идет снова и снова, но при этом элементы окна GUI типа Button реагирует после 100 цикла.

Интересно то, что таймер в консоль время отработки пишет одинаковое на 2 пк :( Видимо с сетевой чего-то не то. Хотя другую ставил тоже...
 

InnI

AutoIT Гуру
Сообщения
4,951
Репутация
1,446
Код:
$time = TimerInit()
$data = TCPRecv($ConnectedSocket[$i][0],65535)
$diff = TimerDiff($time)
Проверьте все ли данные получены в $data и сравните время $diff с установленным в TCPTimeout. Если получены все данные и время меньше TCPTimeout, значит проблема не в функции. Кстати, зачем вам так много данных 65535? Попробуйте уменьшить до 4096 или 1024.
 
Автор
L

La2Angel

Новичок
Сообщения
156
Репутация
1
Попробую, 65535 - Удаленная консоль работает, передает много информации, ну и на заметку, я и так делал:
Код:
TCPRecv($ConnectedSocket[$i][0],30)

Изменений никаких. Дома посмотрю с временем и отпишусь.

1 машина - Проверил время, при получении с опцией в 100, пишет время 100.98998334, данные получены все.
2 машина - точно такие же показатели:(, но реакция на выход из программы обрабатывала в раза 3 дольше.

Вообщем я не знаю уже как описать, но проблема именно на TCPRecv. Т.к. если ее за комментировать, то скрипт работает нормально.
Как я писал уже, если сделать вывод информации в консоль, то без всяких задержек выводиться информация в консоль, а это значит, что цикл полностью отрабатывает в двух случаях, но на 1 из машин, почему-то при подключении клиентов, работа с элементами GUI увеличивается по времени прямо пропорционально количеству клиентов, НО не изменяя времени вывода данных в консоль. Я в тупике :( Блин, видео наглядно снять уже, что ли.
 

InnI

AutoIT Гуру
Сообщения
4,951
Репутация
1,446
La2Angel [?]
при получении с опцией в 100, пишет время 100.98998334, данные получены все
Беру пример из английской справки для функции TCPRecv(). Добавляю измерение времени и устанавливаю 65535
Код:
...
    ; Assign a Local variable the data received.
    $time = TimerInit()
    Local $sReceived = TCPRecv($iSocket, 65535) ;we're waiting for the string "tata" OR "toto" (example script TCPRecv): 4 bytes length.
    $diff = TimerDiff($time)
    MsgBox(0, "", $diff)

    ; Notes: If you don't know how much length will be the data,
    ; use e.g: 2048 for maxlen parameter and call the function until the it returns nothing/error.
...
Время получения данных $diff = 0.07 (проверял как на одной машине, так и на двух в сети). Попробуйте этот пример у себя.
 
Автор
L

La2Angel

Новичок
Сообщения
156
Репутация
1
Так у меня вообще 0.01 пишет, но это на 1 клиента. Я же говорю, проблема не в этом, а в том, что я на 1 машине, таймаут могу выставить хоть в 1000, все равно работает все отлично :smile: Но вот на 2 машине, работает быстро только тогда, когда таймаут ставлю 10 :(
 

qqww22

Новичок
Сообщения
115
Репутация
4
Пиши dll на другом яп и обрабатывай потоком получение данных.
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
qqww22
Ну вот зачем тут потоки? Потоки, потоки.. мания какая то.

La2Angel
Давненько я не работал с сетью, но если я правильно понимаю всю картину, то:
Выставь TCPTimeout в 0, теперь функция TCPRecv не будет ожидать, а только проверять буфер входящих данных. Отличительной особенностью станет выставление флага @Error в -1 при условии, что никакие данные за прошедшее время не пришли.

Вот таким образом последний раз я работал с TCP под AutoIt:
Код:
Func _Recv( ... )
	Local $vRecv
	; ---
	$vRecv = TCPRecv( ... )
	Switch @Error
		Case 0 ; Обрабатываем данные
			...
			Return 1

		Case -1 ; Данных нет
			SetError( 0 )
	EndSwitch
	Return SetError( @Error, 0, 0 )
EndFunc
 
Автор
L

La2Angel

Новичок
Сообщения
156
Репутация
1
Спасибо, ладно, всей сути не решили но хотя бы сделал выводы. Сделаю на 0, просто думал, что так может данные не все принять. А так вот частичный код приема.
Код:
Func recv()
   For $i=1 To $ConnectedSocket[0][0]
	  ; решить проблему тут
	  If $ConnectedSocket[$i][0] <> -1 Then
		 $recv = TCPRecv($ConnectedSocket[$i][0],65535)
		 If $recv <> '' Then
			quantity($recv,$i) ; Проверяем входящее сообщение
		 ElseIf @error Then
			;~ 	Если клиент ушёл, то закрываем сокет
			$KolCon-=1
			WinSetTitle($hParent,'',$title & '('&$KolCon&')')
			GUICtrlSetData($edit, messagestime() & 'IP:' & $ConnectedSocket[$i][1] & ' -> Отключился.' & @CRLF & GUICtrlRead($edit))
			TCPCloseSocket($ConnectedSocket[$i][0])
			For $z = 1 To $guimass[0][0]
			   If $guimass[$z][0] = $ConnectedSocket[$i][0] Then
				  GUIDelete($guimass[$z][1])
				  $guimass[$z][0] = ''
				  $guimass[0][0] -= 1
				  _ArrayClearEmpty($guimass, 0, 1)
				  ExitLoop
			   EndIf
			Next
			$ConnectedSocket[$i][0] = ''
			$ConnectedSocket[$i][1] = ''
			$ConnectedSocket[0][0] -= 1
			_ArrayClearEmpty($ConnectedSocket, 0, 1)
			Terminate()
		 EndIf
	  EndIf
   Next
EndFunc
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
Код:
ElseIf @error Then
            ;~  Если клиент ушёл, то закрываем сокет


В этом блоке у вас ошибка. Как я уже писал выше, "-1" выставляется при отсутствии данных в буфере за прошедшее время, а ваше условие удовлетворит всему, что не равно "0". В данном случае ваши клиенты будут отключаться постоянно.

UPD: Проверил официальную документацию еще раз, теперь "-1" означает "Invalid socket". Совсем ребятам заняться нечем, последнее время они только и делают, что ломают обратную совместимость.
 
Верх