[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Can there be a better way of doing non-blocking data reads with LuaSocket?
- From: "Jerome Vuarand" <jerome.vuarand@...>
- Date: Mon, 10 Nov 2008 11:05:54 +0100
2008/11/10 Sam Roberts <vieuxtech@gmail.com>:
> LuaSocket doesn't have an obvious way to read whatever data is
> available from a socket, if it isn't line delimited or of a known
> size. I found a way, but it seems unnecessarily obscure.
>
> For a project I'm working on, when a socket selects as receivable, I
> want whatever data is available, and I push into another object. I
> don't have any knowledge of how much might be there, and it's binary
> data so using *l is out of the question.
>
> Anyhow, I implemented the following, but I've some questions:
>
> 1 - is this a good way to do it? It seems to work, but also seems a hack.
>
> 2 - why is partial not nil if there is no partial data? It's always
> "", even if emsg isn't "timeout".
>
> 3 - I'd like to replace the standard receive with mine, but every
> client socket seems to get a different metatable. Can I get to the
> table with LuaSocket's client TCP methods, and replace it's receive
> with mine?
>
> 4 - any chance of making "*f" ("frame") a standard part of LuaSocket?
>
>
> --[[-
> - data, emsg, partial = client:receive(pattern[, prefix])
> - data, emsg, partial = client:receive("*f"[, size])
>
> If pattern is not "*f", is identical to client:receive().
>
> Otherwise, return as much data as is available, up to size bytes. If size is
> not specified, it defaults to 4096. This is useful for dealing with a TCP
> stream without knowing the protocol. I.e., transparent proxying of TCP data as
> it arrives.
>
> This pattern requires setting client's timeout to 0, for non-blocking behaviour.
> ]]
> function receive(client, pattern, prefix)
> if pattern ~= "*f" then
> return client:receive(pattern, prefix)
> end
>
> local size = assert(tonumber(prefix or 4096))
> local data, emsg, partial = client:receive(size)
> if not data and partial ~= "" then
> return partial
> else
> return data, emsg
> end
> end
I think you can simply use the "*a" pattern to do what you asked for.
It works just like the code you proposed, except it's not limited to a
fixed amount of bytes and it properly handles the prefix parameter
(which you don't). For example:
client:settimeout(0)
function receive(socket, pattern, prefix)
if string.match(pattern, "^%*f") then
local data, emsg, partial = socket:receive("*a", prefix)
if not data and emsg=='timeout' then
return partial
else
return data, emsg
end
else
return socket:receive(pattern, prefix)
end
end