Making my Network class non-blocking?

I have a refresh spinner which looks nice and everything but when the network class starts sends and receive messages it blocks everything. I want to create a feeling that everything is running smoothly, which is doesn’t when the spinner isn’t moving. Can anyone assist me on how to make this a non-blocking network class or guide to some good resources?

local json = require( "json") local util = require("util.util") local \_G = require( "globals" ) module( ..., package.seeall ) local socket = require("socket") function newConnection( params ) params = params or {} if (not params.server or not params.port) then print( "SERVER OR PORT NOT SPECIFIED" ); return a end local self = {} self.buffer = "" self.server = params.server self.port = params.port self.isOpen = false function self:start( params ) self.callback = params.callback self.sock, err = socket.connect( self.server, self.port ) if ( self.sock == nil ) then print( "COULDN'T CONNECT TO SERVER ( self:start ): ", err ) return false; else print( "Connected." ) end self.isOpen = true self.sock:setoption( "tcp-nodelay", true ) -- disable Nagle's algorithm for the connection self.sock:settimeout(0) self.sock:setoption( "keepalive", true ) return true end function self:close() print( "Closing server connection" ) if self.sock then self.sock:close() self.sock = nil self.buffer = "" end end function self:reconnect() if ( not self.callback ) then print( "NO CALLBACK FUNCTION ON RECONNECT ATTEMPT" ) return false end print( "RECONNECTING TO SERVER" ) self:start({ callback = self.callback}) end function self:isActive() if self.sock == nil then return false else return true end end function self:send( msg, delay ) msg.DeviceID = \_G.DeviceID --""-- Needed for push notifications msg = json.encode(msg) msg = string.format("%05d", #msg + 6) .. msg local function send(message) if (self.sock == nil) then print( "SERVER CONNECTION LOST" ) self:reconnect() return false; end local send\_result, err, num\_byes = self.sock:send( message .. "\n") if (send\_result == nil) then print( "ERROR TRYING TO SEND MESSAGE TO SERVER: "..err..' SENT '..num\_byes..' BYTES' ); if ( err == 'closed') then self:reconnect() end return false; else print( "Message sent : "..json.encode( message ).." - "..send\_result ) end return true end if delay == nil or delay == false then timer.performWithDelay(200, function() send( msg) end ) elseif delay == true then send( msg) end end local counter = 10000 local network\_value = 1 -- Try different values to see if the battery consumption goes down function self:enterFrame() if counter \> network\_value then \_G.Connected = self:isActive() local input,output = socket.select( { self.sock }, nil, 0 ) -- this is a way not to block runtime while reading socket. zero timeout does the trick for i,v in ipairs(input) do ------------- local got\_something\_new = false while true do skt, e, p = v:receive(1) if skt then if skt ~= '\0' then self.buffer = self.buffer..skt else got\_something\_new = true self.buffer = "\_\_JSON\_\_START\_\_"..self.buffer.."\_\_JSON\_\_END\_\_" end end if p then if p ~= '\0' then self.buffer = self.buffer..p else got\_something\_new = true self.buffer = "\_\_JSON\_\_START\_\_"..self.buffer.."\_\_JSON\_\_END\_\_" end end if got\_something\_new == true then break end if not skt then break; end if e then print( "ERROR: "..e ); break; end end -- now, checking if a message is present in buffer... while got\_something\_new do -- this is for a case of several messages stocker in the buffer local start = string.find(self.buffer,'\_\_JSON\_\_START\_\_') local finish = string.find(self.buffer,'\_\_JSON\_\_END\_\_') if (start and finish) then -- found a message! local message = string.sub( self.buffer, start+15, finish-1) self.buffer = string.sub( self.buffer, 1, start-1 ) .. string.sub(self.buffer, finish + 13 ) -- cutting our message from buffer self.callback( message ) else self.buffer = "" break end end end counter = 0 else counter = counter + 1 end end Runtime:addEventListener('enterFrame', self) return self end

Best regards,

Tomas

Not entirely sure if this is part of the problem, but assuming Lua is just a wrapper around “standard” libraries (e.g. http://pubs.opengroup.org/onlinepubs/009695399/functions/setsockopt.html), then setting timeout to exactly 0 might mean block-forever.

Have you tried setting timeout to something really small, but non-zero?  e.g. 0.01

Hi Jbp,

Thanks for your reply.

Yeah, I read that somewhere else so I tried setting it to 0.01 and 0.001 but without any luck.

I experienced with two lines:

self.sock:settimeout(0) local input,output = socket.select( { self.sock }, nil, 0 ) -- this is a way not to block runtime while reading socket. zero timeout does the trick

Best regards,

Tomas

Not entirely sure if this is part of the problem, but assuming Lua is just a wrapper around “standard” libraries (e.g. http://pubs.opengroup.org/onlinepubs/009695399/functions/setsockopt.html), then setting timeout to exactly 0 might mean block-forever.

Have you tried setting timeout to something really small, but non-zero?  e.g. 0.01

Hi Jbp,

Thanks for your reply.

Yeah, I read that somewhere else so I tried setting it to 0.01 and 0.001 but without any luck.

I experienced with two lines:

self.sock:settimeout(0) local input,output = socket.select( { self.sock }, nil, 0 ) -- this is a way not to block runtime while reading socket. zero timeout does the trick

Best regards,

Tomas