Lua TCP Receive Timeout

I am seeing a very simple piece of Lua code timing out when sending over TCP. I can do nearly the same thing in python and it works fine. Both are running locally on my network, not on the hub. How would you port this Python code to a Lua equivalent?

Python

import socket

TCP_IP = '192.168.0.XXX'
TCP_PORT = PPPP
BUFFER_SIZE = 1024
MESSAGE = b"MESSAGE"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()

print("received data:", data.hex())

Lua

local sock, error = assert(socket.tcp())
sock:settimeout(3)
assert(sock:connect('192.168.0.XXX', PPPP))
assert(sock:send("MESSAGE"))

local line, status, partial = sock:receive('*a')
print(string.format('status = %s', status)) -- TIMEOUT

assert(sock:close())

If I don’t set a timeout in Lua , I eventually get a response, but after a very long period of time (~120 sec). I know it isn’t the device since the Python is very fast.

I have tried the receive with ‘*a’, ‘*l’ and 1024. I have to have the timeout or I just sit there forever. I do get data in the partial, but with a timeout status. I’m guessing that the device isn’t closing the connection which is why receive isn’t returning right away. Just not sure why python doesn’t see the same thing.

Python’s recv() call returns any and all bytes UP TO the max passed in (BUFFER_SIZE in your example). Blocks on no data ready, returns with 1-BUFFER_SIZE bytes in the read queue.

Lua’s receive() works on patterns of either:

  • all-until-socket closure (*a)
  • lines (CR/LF delimited) (*l)
  • total bytes (but not fewer, until socket closure). (<number>)

Its based on the file i/o patterns, which do the same operations (with EOF being equivalent to socket closure).

1 Like

This is my understanding as well. I’m not sure how to mimic Python’s behavior. It appears that the device doesn’t close the channel, nor does it provide CR/LF characters. Since the bytes are never 1024, it just sits there.

Oddly enough, I moved the code on to the hub and ran it with cosock instead of LuaSocket. The code ran as desired, but I’d still like it to make sense.

1 Like

This has returned and I now see the stalling behavior on all platforms with Lua. Seems like I will need to figure this out after all. I am getting the data I want and the code works, but every request is “timing out” and the data is returned as a partial, although it has everything in there.

The protocol has some markers in the headers indicating the packet sizes, so I am just going to manually read the bytes by count instead of using the formatting specifiers. The device doesn’t appear to use the control characters needed by the formatting specifiers. I don’t have an explanation for why Python is more forgiving, but I suppose that is for another day.

Do you have any news about it ?

I read somewhere python is non-blocking process and lua is blocking.
That would explain the divergence.

In my case, I am trying to read event stream.
Server keeps the connection open and doesn’t send length. So my request using lua hangs forever.

I had to define timeout to 3s and buffer size to 1.

Yes. You can’t use *a since that will read until the socket closes. Yours will not close with event stream. Use *l to read line by line. You need to read line by line anyway for SSE. SSE will provide you chunk sizes, then you read by buffer length. So it is receive(*l) --> check the chunk length --> receive(length) --> repeat