Что нового

Как по окончании принятия данных по TCP, выйти из цикла

sforce5

Олл фо ЛулзЪ
Сообщения
160
Репутация
41
Вот собсно код:

Код:
While 1
     $recv = TCPRecv($connect, 2048, 1) ; Хэндл коннекта, размер буфера, флаг
     If @error Then ExitLoop
     If $recv <> "" Then FileWrite(@ScriptDir &"\tcp_data.bin", $recv)
WEnd


Как можно сделать чтоб по окончанию принятия данных цикл завершался?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
sforce5 [?]
Как можно сделать чтоб по окончанию принятия данных цикл завершался?
Там ошибку нужно проверять так:

Код:
If @error = -1 Then ExitLoop


в справку иногда заглядывать полезно ;)
 
Автор
sforce5

sforce5

Олл фо ЛулзЪ
Сообщения
160
Репутация
41
CreatoR сказал(а):
sforce5 [?]
Как можно сделать чтоб по окончанию принятия данных цикл завершался?
Там ошибку нужно проверять так:

Код:
If @error = -1 Then ExitLoop


в справку иногда заглядывать полезно ;)

Всё равно не выходит из цикла
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
sforce5 [?]
Всё равно не выходит из цикла
А если проверять «@error <> 0»?

и как определяется что функция больше не возвращает данные?
 
Автор
sforce5

sforce5

Олл фо ЛулзЪ
Сообщения
160
Репутация
41
CreatoR сказал(а):
А если проверять «@error <> 0»?

и как определяется что функция больше не возвращает данные?

Я использую двойной цикл, первый монитор действий (нажатие кнопок), второй получение данных:

Код:
TCPStartup()

While 1
	$nMsg = GUIGetMsg()
	Select 
		Case $nMsg = $GUI_EVENT_CLOSE or $nMsg = $close_btn
			TCPShutdown()
			Exit
		Case $nMsg = $connect_btn
			$connect = TCPConnect($server_ip, $tcp_port)
		Case $nMsg = $go_btn
			TCPSend($connect, "start")
			While 1
				$recv = TCPRecv($connect, 2048, 1)
				If @error Then ExitLoop
				If $recv <> "" Then FileWrite(@ScriptDir &"\tcp_data.bin", $recv)
			WEnd
	EndSelect
WEnd


С сервером проблем нет, а у клиента ошибку эту не могу исправить
 

amel27

Продвинутый
Сообщения
146
Репутация
55
sforce5 сказал(а):
Как можно сделать чтоб по окончанию принятия данных цикл завершался?

встречный вопрос: как определить "окончание принятия данных"?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
sforce5 [?]
С сервером проблем нет, а у клиента ошибку эту не могу исправить
Значит видимо сервер продолжает посылать данные клиенту.
 
Автор
sforce5

sforce5

Олл фо ЛулзЪ
Сообщения
160
Репутация
41
CreatoR сказал(а):
Значит видимо сервер продолжает посылать данные клиенту.

да вроде нет, передал, и опять встаёт на TCPAccept цикл

Код:
While 1
	Do
		$connect = TCPAccept($socket)
	Until $connect <> -1
		
	While 1
		$command = TCPRecv($connect, 4, 1)
		If @error Then ExitLoop
		Switch $command
			Case "start"					
				$size = FileGetSize(@ScriptFullPath)
				$hFile = FileOpen(@ScriptFullPath, 16)

				While $bytesent < $size
					$buff = FileRead($hFile, 2048)
					TCPSend($connect, $buff)
					If @error Then ExitLoop
					$bytesent += 2048
				WEnd
				
				Global $bytesent = 0
				ExitLoop
		EndSwitch
	WEnd
WEnd
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Latoid [?]
очень очень хороший вопрос
Я этот вопрос тоже задал, но меня видимо проигнорировали :blum:

sforce5
А сокет вроде нужно закрывать после чтения...
 
Автор
sforce5

sforce5

Олл фо ЛулзЪ
Сообщения
160
Репутация
41
CreatoR сказал(а):
и как определяется что функция больше не возвращает данные?

У меня GUI клиента не работает после входа в цикл, тем более задал опцию TrayIconDebug где видно что "застыло" на TCPRecv

CreatoR сказал(а):
А сокет вроде нужно закрывать после чтения...

Сокет закрывается при выходе из самой программы
 

Latoid

Знающий
Сообщения
95
Репутация
11
CreatoR сказал(а):
Latoid [?]
очень очень хороший вопрос
Я этот вопрос тоже задал, но меня видимо проигнорировали :blum:

:smile: Я, правда, тот пост удалил случайно.
sforce5
Из справки по TCPRecv:
Return ValueSuccess: Returns binary/string sent by the connected socket.
Failure: Returns "" and set @error
@error: -1 Socket error
windows API WSAGetError return value (see MSDN).
Т.е. флаг @error принимает значение -1 только при ошибке сокета, а не при прекращении передачи данных от сервера. Т.е. при нормальном рабочем соединении @error никогда не станет -1 и цикл превращается в бесконечный. Т.е. делать нужно примерно так:
Код:
$ret = _WaitTcpResponse()
While Not ;[проверяем, что cодержимое переменной $ret не содержит признаков конца передачи]
	$ret &= _WaitTcpResponse()
	If @error Then ExitLoop
WEnd
ConsoleWrite ($ret & @CRLF)


Func _WaitTcpResponse($timeout = 30000)
	Local $ret
	Local $T = TimerInit()
	While 1
		If TimerDiff($T) > $timeout Then
			Return -1
		EndIf
		$ret = TCPRecv ($connect, 2048)
		If $ret <> "" Then
			Return $ret
		EndIf
	WEnd
EndFunc   ;==>_WaitTcpResponse

Этот код создавался для текстовых данных. Не знаю, и не могу проверить какие особенности у бинарных данных. Привожу его, чтоб стал понятен принцип

У меня GUI клиента не работает после входа в цикл, тем более задал опцию TrayIconDebug где видно что "застыло" на TCPRecv
Так надо в качестве теста принять файл через telnet и посмотреть
 
Автор
sforce5

sforce5

Олл фо ЛулзЪ
Сообщения
160
Репутация
41
Выдаёт ошибку:

19fbb5d85adf.png
 

Latoid

Знающий
Сообщения
95
Репутация
11
:smile:
Я же писал:
Код:
While Not ;[проверяем, что cодержимое переменной $ret не содержит признаков конца передачи]
Т.е. после Not надо добавить проверку на то, что переменная $ret содержит признаки конца передачи. Что есть "признак конца передачи"? Сиё вопрос. POP3 или IMAP4 серверы, например, как выполнят переданную им команду (отдадут клиенту текст письма, например), обязательно в конце допишут что-то вроде "ОК [бла-бла]". Тогда получится
Код:
While Not StringRegExp ($ret, "ОК \[бла-бла\]")
Что есть в твоем случае "признак конца передачи"? Не знаю. Прими файл telnet'ом и посмотри.
 
Верх