我有一个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是一个全局变量,因为我不想为每个“blah”实例打开一个新的套接字。有什么方法可以让套接字等待接收所有数据(例如,直到字符串为空终止),然后打印数据??
更新 我一直在尝试不同的方法将size参数传递给receive方法,如下所述: http://w3.impa.br/~diego/software/luasocket/tcp.html 然而,这些似乎没有任何影响,例如。
response,data = socket:receive(65536)
response,data = socket:receive('a*')
答案 0 :(得分:1)
我通过网络传递字符串或二进制数据时经常使用的解决方案是首先传递字段的大小。然后,您可以运行接收,直到它与已知长度匹配。这意味着服务器将如下所示:
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
答案 1 :(得分:0)
我相信luasocket库中存在一个错误(至少是Corona SDK使用的版本),这会导致它通过TCP间歇性地破坏大型数据包。这已得到Corona SDK开发人员的确认。怀疑问题是luasocket库没有正确处理TCP重试请求。我试图通过将我的帧大小限制为小于标准网络(ipv4)MTU来避免错误,希望这将避免数据包碎片并防止出现问题。我通过将数据包数据自己制作成较小的帧然后在另一端重新组装来实现这一点。 IPV4的MTU通常是576字节,我尝试用512安全。
答案 2 :(得分:0)
为了澄清,socket.receive
的正确参数是'*a'
而不是'a*'
- 这可能就是您没有从套接字接收所有数据的原因。