Что нового

TCPRecv даже с параметром MaxLen 200000 принимает всего около 1400 байт за раз

Sαuron

Новичок
Сообщения
45
Репутация
1
Сделал сервис с TCP обменом данных, всплыла проблема
Код:
; Прием данных
$client_timer = TimerInit()
$client_dannie = ''
While ($client_dannie = '') And (TimerDiff($client_timer) < 5000)
	  $client_dannie = TCPRecv($client_socket, 200000, 1)						; Пытаться принимать данные в ответ от сервера (максимум 200к байт)
WEnd

Вот такой код приема данных на клиенте принимает за раз всего первые 1400-1500 байт и все (дело не в таймауте 5сек), как правильнее всего принимать от сервера все байты?
P.S. Байты могут быть любыми от 0x00 до 0xFF надо безошибочно принимать все
 
Автор
S

Sαuron

Новичок
Сообщения
45
Репутация
1
hedji сказал(а):
Знаю, а принимать то как? Мне надо принять все байты по установленному соединению, а не первые 1400, у функции TCPRecv всего 1 параметр "MaxLen", которому пофиг на значения больше 1400, а точнее больше 1400 просто не приходит, оффсетов никаких у него я не вижу, это все бред какой-то

P.S. Если сделать запрос к серверу через браузер, то браузер получит все байты, мне нужен этот же эффект в клиенте на AutoIt
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Если будет передаваться больше 1400, то поделится на несколько пакетов, которые будут переданы последовательно. А на принимающей стороне должны быть склеены обратно.
Как именно есть в примере для функции TCPRecv
Код:
While 1 ; Цикл сообщений GUI
        If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop

        ; Попытка получить (до) 2048 байт
        $sData = TCPRecv($iSocket, 2048)

        ; Если возвращает ошибку @error, это означает, что сокет отключен. Соответственно выход из цикла.
        If @error Then ExitLoop

        ; Конвертирует бинарные данные из UTF-8 в нативный UTF-16
        $sData = BinaryToString($sData, 4)

        ; Обновляет окно приёма сообщений полученными данными
        If $sData Then GUICtrlSetData($iEdit, _
                $szIP_Accepted & " > " & $sData & @CRLF & GUICtrlRead($iEdit))
    WEnd
 
Автор
S

Sαuron

Новичок
Сообщения
45
Репутация
1
hedji сказал(а):
Если будет передаваться больше 1400, то поделится на несколько пакетов, которые будут переданы последовательно. А на принимающей стороне должны быть склеены обратно.
Как именно есть в примере для функции TCPRecv
Код:
While 1 ; Цикл сообщений GUI
        If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop

        ; Попытка получить (до) 2048 байт
        $sData = TCPRecv($iSocket, 2048)

        ; Если возвращает ошибку @error, это означает, что сокет отключен. Соответственно выход из цикла.
        If @error Then ExitLoop

        ; Конвертирует бинарные данные из UTF-8 в нативный UTF-16
        $sData = BinaryToString($sData, 4)

        ; Обновляет окно приёма сообщений полученными данными
        If $sData Then GUICtrlSetData($iEdit, _
                $szIP_Accepted & " > " & $sData & @CRLF & GUICtrlRead($iEdit))
    WEnd

Не знал, что TCPRecv последовательно принимает. А принцип работы у нее какой? Она ждет входящие данные или хватает то, что уже пришло? Просто для первого случая нужен таймаут, для второго надо ждать входящие данные...
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Код:
$BigFileForTransfer ;большой файл для передачи
;передача
While $BigFileForTransfer
    TcpSend() ;откусываем от файла кусок 1400 и шлем через сеть
wend

;прием
While 
    TCPRecv() ;принимаем кусок 1400 и ждем следующий, приклеиваем 1й кусок ко 2му и т.д. пока не соберем из кусков $BigFileForTransfer
Wend
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Sαuron

Предупреждение За нарушение общих правил (пункт В.2):
Старайтесь избегать “Over quoting” (преувеличенное цитирование) - цитируйте только необходимую часть сообщения, которая наилучшим образом подчеркнёт суть цитируемого.


С уважением, ваш Глобальный модератор.
 
Автор
S

Sαuron

Новичок
Сообщения
45
Репутация
1
hedji сказал(а):
Код:
$BigFileForTransfer ;большой файл для передачи
;передача
While $BigFileForTransfer
    TcpSend() ;откусываем от файла кусок 1400 и шлем через сеть
wend

;прием
While 
    TCPRecv() ;принимаем кусок 1400 и ждем следующий, приклеиваем 1й кусок ко 2му и т.д. пока не соберем из кусков $BigFileForTransfer
Wend

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

Код:
TCPSend($client_socket, '1234')	; Делаем запрос, сервер должен ответить

; Прием данных
$client_timer = TimerInit()
$client_dannie = ''
$client_dannie_0 = ''
While TimerDiff($client_timer) < 5000
	  $client_dannie_0 = TCPRecv($client_socket, 128)
	  If $client_dannie_0 = '' Then
			ExitLoop
	  Else
			$client_dannie &= $client_dannie_0
	  EndIf
WEnd


Вот тут у меня возникает сомнение, паузы после TCPSend никакой нет, сразу идет TCPRecv в цикле, мне кажется это все закончится тем, что TCPRecv вернет пустую строку (сервер еще не успел ответить) и произойдет выход из цикла с пустыми данными... Нужен 100% прием данных, т.е. надо дождаться их прихода и принимать, как понять, что данные пришли и их можно захватывать TCPRecv, я не пойму...
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Вы это все пытаетесь проделать в одном скрипте что ли?
Скрипт-сервер должен быть запущен первым, открыть нужный порт и висеть в бесконечном цикле этот порт прослушивать, при получении данных как-то их обрабатывать, писать их в консоль например.
Потом запускаем скрипт-клиент, шлем данные и смотрим, что получили на сервере.
 
Автор
S

Sαuron

Новичок
Сообщения
45
Репутация
1
hedji сказал(а):
Вы это все пытаетесь проделать в одном скрипте что ли?
Скрипт-сервер должен быть запущен первым, открыть нужный порт и висеть в бесконечном цикле этот порт прослушивать, при получении данных как-то их обрабатывать, писать их в консоль например.
Потом запускаем скрипт-клиент, шлем данные и смотрим, что получили на сервере.
Мы не понимаем друг-друга кажется. Вот специально для теста поднял сервер на 31.23.74.156:1200, он вернет 5000 символов "0", на конце "1" (или же 4999 байт 0x30 и 0x31 на конце), если к нему обратиться из браузера Chrome. Как мне гарантированно получить эти 5к символов? Наработку выше кинул.
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Код:
$sData = InetRead("http://31.23.74.156:1200/")
$sData = BinaryToString($sData, 4)
ConsoleWrite($sData & @CRLF)
 
Автор
S

Sαuron

Новичок
Сообщения
45
Репутация
1
hedji сказал(а):
Код:
$sData = InetRead("http://31.23.74.156:1200/")
$sData = BinaryToString($sData, 4)
ConsoleWrite($sData & @CRLF)

Отличный способ, + в репу. Но хотелось бы принципиально еще на TCP аналогичное и не менее надежное сделать, реально ли?

Да все же на TCP только делать прием, т.к. http протокол добавляет целый ряд заголовков ненужных абсолютно, которые нагружать только будут...
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Опишите более подробно решаемую задачу.
Сначала был вопрос про TCPRecv(), потом выяснилось, что есть некий сервер, работающий по HTTP (т.е. мы сначала должны послать ему http-запрос, потом получить ответ).
Что именно Вы пытаетесь сделать? Написать сервер или клиент для существующего сервера?
 
Автор
S

Sαuron

Новичок
Сообщения
45
Репутация
1
hedji сказал(а):
Опишите более подробно решаемую задачу.
Сначала был вопрос про TCPRecv(), потом выяснилось, что есть некий сервер, работающий по HTTP (т.е. мы сначала должны послать ему http-запрос, потом получить ответ).
Что именно Вы пытаетесь сделать? Написать сервер или клиент для существующего сервера?

Все крутится вокруг первого сообщения, мне надо принимать все данные с 31.23.74.156 по порту 1200, используя TCP.
Для теста крутится небольшой скрипт который на любой входящий запрос ответит 5000 символами "0" и "1" на конце.
Если их получится надежно принимать, не ожидая лишнего времени, значит проблема решена


Добавлено:
Сообщение автоматически объединено:

Удалось самому доработать, вот...
Можно ли как-то доработать еще? Возможны ли непредвиденные ошибки в этом коде?

Код:
$client_timer = TimerInit()
$client_dannie = ''												; Все данные
$client_dannie_new = ''											; Порция данных
$client_recv_start = 0											; Флаг приема
While TimerDiff($client_timer) < 5000							; Тайм аут через 5 секунд попыток приема
	  $client_dannie_new = TCPRecv($client_socket, 128)
	  If $client_dannie_new = '' Then							; Если данные не поступили
			If $client_recv_start = 1 Then						;... и прием уже идет
				  ExitLoop										;... конец приема
			EndIf
	  Else
			$client_recv_start = 1								; Если данные поступили - прием начался
	  EndIf
	  $client_dannie &= $client_dannie_new
WEnd


Ладно, это другая тема уже, скорее всего, закрываю.
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Код:
TCPStartup()
 $iSocket = TCPConnect("31.23.74.156", "1200")
 TCPSend($iSocket, '1234')
 $client_timer = TimerInit()
 While TimerDiff($client_timer) < 5000
	 $sData = TCPRecv($iSocket, 2048)
	 $sData = BinaryToString($sData, 4)
	 ConsoleWrite($sData)
 WEnd
 
Автор
S

Sαuron

Новичок
Сообщения
45
Репутация
1
hedji сказал(а):
Код:
TCPStartup()
 $iSocket = TCPConnect("31.23.74.156", "1200")
 TCPSend($iSocket, '1234')
 $client_timer = TimerInit()
 While TimerDiff($client_timer) < 5000
	 $sData = TCPRecv($iSocket, 2048)
	 $sData = BinaryToString($sData, 4)
	 ConsoleWrite($sData)
 WEnd
Уже сделал все, а этот код не будет работать, т.к. символы не шифруются 4 битами, чтоб быть увереным в том, что код символа не будет занимать две порции TCPRecv (конец первой и начало второй), тем более UTF8... произойдет разрыв какого-то символа на другую порцию TCPRecv и BinaryToString попытается превратить в символ кусок символьного кода, в итоге выдаст лишний символ или любой другой бред некорректный. Ну и досрочного выхода из приема тут тоже нет, 5 сек он будет добавлять пустые данные...
 
Верх