Что нового

Связка команд TCPSend-TCPRecv

autoall

Новичок
Сообщения
21
Репутация
0
У меня есть задача - передать информационный пакет между двумя программами. Открыл справку, поразбирался с примерами.

Накатал два таких скрипта:

Сервер:
Код:
ServerASH()

Func ServerASH()

	TCPStartup()

    Local $ip = "127.0.0.1"
    Local $port = 65432

    Local $lsocket = TCPListen($ip, $port, 100)

    If @error Then
        MsgBox(4096 + 16, "Сервер", "Не удалось прослушать сокет, @error = " & @error)
		TCPCloseSocket($lsocket)
		TCPShutdown()
    EndIf

    Local $socket = 0
    Do
        $socket = TCPAccept($lsocket)

        If @error Then
            MsgBox(4096 + 16, "Сервер", "Не удалось принять входящее соединение, @error = " & @error)
            Return False
        EndIf
    Until $socket <> -1

	Do
		$din = TCPRecv($socket, 2048, 1)
	Until StringCompare($din,"") = 0

	MsgBox(4096, "Сервер", BinaryToString($din, 4))

    TCPCloseSocket($socket)
	TCPCloseSocket($lsocket)
	TCPShutdown()

EndFunc


Клиент:
Код:
ClientASH()

Func ClientASH()

	TCPStartup()

    Local $ip = "127.0.0.1"
    Local $port = 65432

    Local $socket = TCPConnect($ip, $port)

    If @error Then
        MsgBox(4096 + 16, "Клиент", "Не удалось подключиться, @error = " & @error)
		TCPCloseSocket($socket)
		TCPShutdown()
    Else
        MsgBox(4096, "Клиент", "Успешное подключение")

		Local $dout = "HELLO!!!"

		TCPSend($socket, StringToBinary($dout, 4))
	EndIf

	TCPShutdown()

EndFunc


Компилирую и запускаю сервер.
Затем запускаю из IDE клиент.

На сервере получаю после запуска клиента пустую строку. И все.

Я хочу реализовать такой алгоритм. Установлен факт соединения через TCPAccept. После факта установки соединения нужно работать на прием, пока данные будут идти и куда-то их сливать (в массив, например, или в файл - не суть важно). После того как порт закроется - выходим из цикла и обрабатываем полученные данные. И после обратотки чего-нибудь отправляю клиенту - хорошо мол, или повторите передачу.

Скопились вопросы, которые непонятны из мануала.
1) Непонятно как работает TCPRecv.
Установлен факт соединения через TCPAccept. После этого я получаю пустую строку и почему-то вываливаюсь из цикла TCPRecv. Как я оттуда выхожу, если строка пустая!!! Как зациклить приемник? В идеале надо намутить свой протокол. Будет старт-байт, байт размера посылки и стоп байт. И вот все это дело получим, обсчитав и проверив, что стоп соответствует стопу - типа тогда выходим из цикла. Но как тогда мне организовать цикличность? Вот послал я сервер, настроенному для приема 4кбайт пакет через TCPSend пакет из тридцати байт - он их целиком получит? Или может порвать? С какой тогда периодичностью TCPRecv дергать? Как осуществить паузу между чтениями - через Sleep?
2) Откуда получает данные TCPRecv? По идее какой-то буфер же где-то должен быть в системе? Как понять его размер? Не вопрос, если я захочу получить пару килобайт. А если мне надо отправить бинарный файл размером 10 мегабайт? Соответственно - а TCPSend можно такой объем засунуть считав файл через ReadFile или надо будет как-то файл разбивать на куски и их отправлять?

Ну вот как-то так немного сумбурно.
Но сильно хочется работать по сети)
Для начала хочу сделать передачу файла с одного компа на другой с командой куда этот файл положить на приемном компе =) Но пока никак не могу осилить простую однократную передачу.
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
autoall
http://autoit-script.ru/index.php?topic=18482.0

Смотрели? Во всех аспектах подходит для реализации вашей задачи.
 
Автор
A

autoall

Новичок
Сообщения
21
Репутация
0
Не видел. Прикольно.

Но я еще хочу сделать сам. Пусть будет просто и коряво, но сам)) А потом либо улучшать, либо да - ваше решение очень интересно)

Просто вроде все понятно. А не работает...
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
autoall
1) Вы вызываете TCPShutdown сразу же после TCPSend
-Нельзя так делать, ваши данные попросту не передаются. Делайте задержку ( к примеру 10ms ) и закрывайте сокет.

2) Until StringCompare($din,"") = 0
-Этот метод более неактуален. Используйте:

Код:
Until Not @Error

или
Код:
Until @Error <> -1


@Error = -1 означает, что сервер промолчал время равное TCPTimeout.
@Error = 0 означает, что были приняты данные от сервера.
 
Автор
A

autoall

Новичок
Сообщения
21
Репутация
0
firex [?]
Вы вызываете TCPShutdown сразу же после TCPSend
От оно! Теперь я понял. Я думал сначала отсылается, а после этого программа выполнится дальше.
 
Автор
A

autoall

Новичок
Сообщения
21
Репутация
0
В процессе работы возник вопрос.

Я отправляю данные: TCPSend ( mainsocket, data )
Я получаю данные: TCPRecv ( mainsocket, maxlen [, flag = 0 ] )

Сначала я гонял мало данных - в пределах одного килобайта. И все было нормлаьно, я отладил взаимодействие скриптов. Передатчик читал текст из фала и высылал приёмнику, который этот текст получал, создавал файл и в него его сбрасывал.
Потом я поднял maxlen до 20971520 (20Мб). И у меня перестало все работать. На приёмнике видно что сыпется мусор, структуры пришедшего пакета не видно.

А есть какие-то ограничения на объём отправляемых данных?


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

Кажется я осознал свою ошибку - TCP пакет-то не резиновый же... Т.е. по длине ограничение уже как максимум в 64кб.
Но все же интересно - какой максимальный объём буфера у TCPRecv может быть? Т.е. сколько за раз я могу передать данных через TCPSend?
 

ВиталийВВ

Новичок
Сообщения
177
Репутация
0
Добрый день!
Взял эти примеры, внес изменения, попробовал - не работает :-( что не так делаю? (только разбираться начал в протоколах).
Сервер в сообщении выводит пустую строку.
Пробую на одном компьютере, ИП адрес как в примере пишу.

Код:
ServerASH()

Func ServerASH()

    TCPStartup()

    Local $ip = "127.0.0.1"
    Local $port = 65432

    Local $lsocket = TCPListen($ip, $port, 100)

    If @error Then
        MsgBox(4096 + 16, "Сервер", "Не удалось прослушать сокет, @error = " & @error)
        TCPCloseSocket($lsocket)
		Sleep(1000)
        TCPShutdown()
    EndIf

    Local $socket = 0
    Do
        $socket = TCPAccept($lsocket)

        If @error Then
            MsgBox(4096 + 16, "Сервер", "Не удалось принять входящее соединение, @error = " & @error)
            Return False
        EndIf
    Until $socket <> -1

    Do
        $din = TCPRecv($socket, 2048, 1)
		Sleep(1000)
    Until Not @Error

    MsgBox(4096, "Сервер", BinaryToString($din, 4))

    TCPCloseSocket($socket)
    TCPCloseSocket($lsocket)
	Sleep(1000)
    TCPShutdown()

EndFunc


Код:
ClientASH()

Func ClientASH()

    TCPStartup()

    Local $ip = "127.0.0.1"
    Local $port = 65432

    Local $socket = TCPConnect($ip, $port)

    If @error Then
        MsgBox(4096 + 16, "Клиент", "Не удалось подключиться, @error = " & @error)
        TCPCloseSocket($socket)
		Sleep(1000)
        TCPShutdown()
    Else
        MsgBox(4096, "Клиент", "Успешное подключение")

        Local $dout = "HELLO!!!"

        TCPSend($socket, StringToBinary($dout, 4))
		Sleep(1000)
    EndIf

	Sleep(1000)

    TCPShutdown()

EndFunc
 
Верх