Code Snippet - how to do non blocking multiplexed raw socket transmission

This took me a while to work out but here is a example of how to do send
and receive on a single socket connection without blocking. I have a real time
game server I wrote using the guts (ioloop portion) from the facebook python tornado
web server. This is the snippet of code that I use to talk to it send, rcv on the same
socket connection without blocking the app. If anyone tries doing it with coroutines good
luck to ya I could not make that work reliably.

[lua]require “socket”
conn = socket.connect(“127.0.0.1”,8000)
_msgsendtable = {}
–send
function _mrcv(connection,rcallback)
connection:settimeout(0)
local s, status = connection:receive()
if s ~= nil then
rcallback(s)
end
end
–receive
function _msend(connection)
local cnt = #_msgsendtable
if cnt > 0 then
for key,msg in pairs(_msgsendtable) do
if msg ~= nil then
connection:send(msg … “\r\n”)
end
_msgsendtable[key] = nil
end
end
end

–send function queues data for transmission
function msgsend(data)
table.insert(_msgsendtable,data)
end

–receive data is passed to this callback
function message_recvd(data)
print(data)
end

–setup timers to handle update and receive
timer.performWithDelay(1,function() _mrcv(conn,message_recvd) end,0)
timer.performWithDelay(1,function() _msend(conn) end,0)

–test send json messages
msgsend("[“m”,“br”,“a”]")
msgsend("[“m”,“br”,“b”]")
msgsend("[“m”,“br”,“c”]")
msgsend("[“m”,“br”,“d”]")
msgsend("[“m”,“br”,“e”]") [/lua]

There is no error trapping or anything of that sort in this routine that is a exercise left to the reader. I did test this some by placing this code snippet in “Tilt Monster” broadcasting accelerometer data to a few connected clients and it did not seem to mess with the games performance at all. [import]uid: 14451 topic_id: 10897 reply_id: 310897[/import]

Ive messed around a lot with this and you cant really use sockets for real time 30fps games and such.

Firstly the connection:settimeout(0) is non blocking except that it will block once the connection starts so if it takes 2 seconds to complete the connection, Corona will hang for that 2 seconds.

Doing it to your device is cheating, even doing it from simulator to simulator is cheating, this doesn’t work reliably when on an actual device.

This is not correct, connection:settimeout(0), it needs to be connection:settimeout( 0.01 ) as when on the device it needs to wait a little bit to see if a connection is starting. If both sending and receiving wait 0 seconds the chances of those 2 devices doing it at the exact same time is very small. This just doesnt work.

The best way ive found is for one device to use the async http connection and the other device to use socket with around a 0.01 , 0.02 timeout. This can still cause the app running the socket to slow down.

Ive implemented a version of the above in www.coronaremote.com.

My first version just used sockets, the newer versions use both sockets and the async http.

Just so you know though I wouldn’t recommend going down the socket route for in game stuff. It can really degrade your app and on wifi the iPhone doesn’t have the strongest connection and the slowest connection can bring the whole down. [import]uid: 5354 topic_id: 10897 reply_id: 39741[/import]

Actually this is very usable at least for what I am doing and I have tried it on multiple devices, simulator, wifi, 3g etc and it worked fine on all of them. However you have peaked my interest and for grins I am going to try async http to a tornado server and see what sort of performance difference there is if any. [import]uid: 14451 topic_id: 10897 reply_id: 39907[/import]

I though the same thing, then I released the app and it turns out not everybody’s wifi is as strong as mine and if the network is being used by other things / people it can really suffer.

You can see a user response here http://developer.anscamobile.com/forum/2011/01/24/slowdown

The async connection paired with the socket allows one device to run totally non blocking, the other if set to about 0.01 will wait just enough time each loop to see if a async connection is being sent.

This way seems to give the max number of connections the network will allow / handle.

On a normal socket I was getting about 10 connections per second as the sockets could only wait for 0. With async I can get 20+ [import]uid: 5354 topic_id: 10897 reply_id: 39923[/import]

Sorry, checking the other posts I set the timeout to 0.001 and not 0.01. [import]uid: 5354 topic_id: 10897 reply_id: 39924[/import]