Hi,
I work with the network library quite a bit when building cloud bits. I wanted to share some code that shows how to create an asynchronous (non-blocking) socket connection in Corona. This is a method that works for me, but I’m sure you could approach this in different ways. If you’re not sure what an async socket is, then you probably don’t need it.
The following will only work in a Corona project due to some usage of the internal SDK.
[lua]
–==============================================================–
–== Init TCP socket
–==============================================================–
local sock = require( ‘socket’ ).tcp()
–==============================================================–
–== Init message queue
–==============================================================–
local msg_queue = {}
local function checkMessageQueue( client )
for _, msg in ipairs( msg_queue ) do
client:write( msg … ‘\r\n’ )
end
end
–==============================================================–
–== Socket connection + options
–==============================================================–
local ok, msg = sock:connect( host, port )
if not ok then
error( msg )
end
sock:settimeout( 0 )
sock:setoption( “tcp-nodelay”, true )
–==============================================================–
–== Socket loop
–==============================================================–
local tick = function()
local input, output = sock.select( {sock}, {sock}, 0 )
for _, client in ipairs( input ) do
local data, err, partial = client:recieve(’*l’)
if data and not err then --incoming!
--data contains string line from client
else
if err == ‘closed’ then
--do close stuff
elseif err == ‘timeout’ then
--handle client timeout
else
error( err ) --catch-all error
end
end
end
--pump message queue
for _, client in ipairs( output ) do
checkMessageQueue( client )
end
end
–==============================================================–
–== Start socket loop
–==============================================================–
local s_loop = timer.performWithDelay( 50, tick, -1 )
[/lua]
Sending a message:
To send a message over the connection, it must be added to the message queue, which will be sent over the first available opening in the loop.
[lua]
table.insert( msg_queue, “Hello server!” )
[/lua]
What’s going on here?
From a high-level overview, we are using some of the methods of the socket
library to create a “send/receive” loop, which would normally be blocking (freeze all on-screen activity). We use the performWithDelay
method to create the “timer loop”, which is actually a kind of light thread. By co-opting the timer, we can create an “async” style socket.
The argument “*l” in the sock.select() method is allowing us to use line endings as a message delimiter. Every 50 ms – anything below that barely registers to the human eye – the loop will trigger.
Because we are looking for line endings (\r\n) you must make sure the network data being sent to the Corona client is properly terminated with a newline, generally represented with ‘\r\n’
Within the loop there is a check for waiting sockets (here we are only using one) and if the socket has data, it’s pulled. If a message is queued, it’s sent. And around we go.
This code was extracted from a larger client module for Coronium GS, it should work as shown, but let me know if something is acting wonky.
References:
https://docs.coronalabs.com/api/library/timer/performWithDelay.html
https://docs.coronalabs.com/api/library/socket/index.html
http://w3.impa.br/~diego/software/luasocket/reference.html
Cheers.