Lua-сокет получает размер строки - PullRequest
0 голосов
/ 20 июля 2011

У меня есть скрипт Lua, который рекурсивно отправляет команды и получает данные обратно через сокетное соединение, используя NSE (механизм сценариев nmap).Кажется, что он обычно работает, пока не получит большую строку назад, а затем урезает полученные данные.При отправке следующей команды данные после проходят через усечение, которое должно было быть получено в предыдущей команде (за которым следуют правильные данные).упрощенный пример вывода ниже.Примечание. «Data38» усекается и продолжается в следующем экземпляре команды:

"send command1"
"recieved data ="
data1
data2
data3
....
....
....
data37
da 
**returning**
"send command2"
"received data ="
ta38 (should be from command1)
data39 (should be from command1)
etc etc etc

пример кода выглядит следующим образом:

local function blah(id)

local response
local data
local commmand

command = "dir..id"

socket:send(command)
response,data = socket:receive()

print(data)

--do recursion her depending on data results.

 print "**returning**"
 return

action = function(host,port)
     socket = nmap.new_socket()
     socket:connect(host,port)
     socket:set_timeout(15000)
     test = blah(id)
return test

Проблема, как представляется, заключается в том, что сокет может принимать толькоопределенное количество байтов, а затем возвращается.Socket - это глобальная переменная, так как я не хочу открывать новый сокет для каждого экземпляра «бла».Есть ли способ заставить сокет ждать получения всех данных (например, до тех пор, пока строка не завершится нулем), а затем распечатать данные ??

Обновление Я пробовал разныеподходы для передачи параметра размера в метод приема, как указано в: http://w3.impa.br/~diego/software/luasocket/tcp.html Однако, похоже, они не имеют никакого эффекта, например.

response,data = socket:receive(65536)
response,data = socket:receive('a*')

Ответы [ 3 ]

1 голос
/ 20 июля 2011

Решение, которое я всегда использовал при передаче строки или двоичных данных по сети, заключается в том, чтобы сначала передать размер поля. Затем вы можете запустить прием, пока он не совпадет с известной длиной. Это означает, что сервер будет выглядеть так:

command,err_msg=socket:receive()
-- build response
socket:send(string.len(response))
-- Note, you should also check for incomplete sends and 
-- run this in a loop until all data has been sent
socket:send(response)

И клиент будет выглядеть так:

socket:send(command)
resp_len,err_msg = socket:receive()
response=""
repeat
  resp_cur,err_msg = socket:receive(resp_len - string.len(response))
  if resp_cur then
    response = response .. resp_cur
  end
until !resp_cur or string.len(response) >= resp_len end
-- handle any errors from an incomplete receive here
0 голосов
/ 10 декабря 2013

Просто чтобы уточнить, правильный параметр для socket.receive равен '*a', а не 'a*' - возможно, поэтому вы не получаете все данные из сокета.

0 голосов
/ 24 декабря 2012

Я считаю, что в библиотеке luasocket есть ошибка (по крайней мере, в версии, используемой Corona SDK), из-за которой она периодически портит большие пакеты по TCP. Это было подтверждено разработчиками Corona SDK. Предполагается, что проблема заключается в том, что библиотека luasocket не обрабатывает запросы TCP Retry должным образом. Я пытаюсь обойти ошибку, ограничивая размер моего кадра меньшим, чем стандартный сетевой (ipv4) MTU, надеюсь, это позволит избежать фрагментации пакетов и предотвратить возникновение проблемы. Я добиваюсь этого, самостоятельно разбивая пакетные данные на меньшие кадры, а затем собирая их на другом конце. MTU для IPV4 обычно составляет 576 байтов, я пытаюсь с 512 для безопасности.

...