现在的位置: 首页 > 综合 > 正文

concurrentLua和copas以及luasocket集成的简单示例

2013年05月25日 ⁄ 综合 ⁄ 共 4608字 ⁄ 字号 评论关闭

require'concurrent'
require'cltime'
require'socket'

concurrent.setoption('trapexit',true)

local out=io.write

port=1888
nodename='master@linkerhp'

concurrent.init(nodename)
out('concurrent node name:'..nodename.."/n")


--tcpport=socket.tcp()
--tcpport:bind("*",port)
--tcpport:settimeout(0)
require'copas'
local tcphandlers={}
local function tcphandler(sock)
  clientip,clientport=sock:getpeername()
  sock=copas.wrap(sock)  
  sock:settimeout(0)
  
  clientid=clientip..':'..clientport
  tcphandlers[clientid]='connected'
  
  while true do
    local data=sock:receive("*l")-- receive a line
    --if tcphandlers[clientid]=='connected' then
      if data then
        out('copas:/"'..data..'/"')
        out"/n"
        concurrent.send('master',{cmd='tcpdata',
                                                   from=sock,
                                                   clientid=clientid,
                                                   ['data']=data})
      end
      --sock:send(data)        
      --out'handler step/n'
    --else
      --return;
    --end
  end
end
tcplistensock=socket.bind("*",port)
copas.addserver(tcplistensock,tcphandler)

-- udp


local udpinit=function(port)
  local u=socket.udp()
  collectgarbage('collect')
  u:settimeout(0)
  --u:setoption('reuseaddr',true)
  ret,err=u:setsockname("*",port)
  if not ret  then 
    out('bind error:'..err)
    concurrent.exit('port:'..port..' bind error.')
  end
  out('udp listening at '..port..'/n')
  out'/n'
  return u;
end
local function udpfini(udpsock)
  udpsock:close()
end
local udpstep=function(udpsock)
  local data,ip,port=udpsock:receivefrom(1024)
  
  if data then
    --out('udp receivefrom '..ip..':'..port..' '..data..'/n')
    --out(port)
    concurrent.send('master',{cmd='udpdata',
                                                   from=udpsock,
                                                   ['clientip']=ip,
                                                   ['clientport']=port,
                                                   ['data']=data})
    out'=/n'
    
    --udpsock:sendto(data,ip,port)
  end
  --out'udp step/n'
end

--udppkt=0
--function incudppkt() udppkt=udppkt+1 end
--function getudppkt() return udppkt end
-- concurrent main process
--local udpsock=udpinit(port)-- must be here!!!!!!!!!!!!!!!!!!!!!!!!
local master=function()
  out"master inited./n"
  selfpid=concurrent.whereis('master')
  out('selfpid:'..selfpid)
  local udplistener={}
  local tcplistener={}
  
  local udpsock=udpinit(port)
  
  if not udpsock then concurrent.exit('udp init failed.') end
  
  concurrent.send('monitor',{from=selfpid,cmd='started',['udpsock']=udpsock})
  while true do
          out'#'
    copas.step(0.1)-- noblock
    udpstep(udpsock)
    local msg=concurrent.receive(100) -- timeout
    --if not msg then out'master timeout/n'; end
    --io.flush()
    if msg then
      if msg.cmd=='new udp' then
      
      elseif msg.cmd=='accept tcp' then

      elseif msg.cmd=='tcpdata' then
        out('master got a tcp data:'..msg.data)
        out'/n'
        msg.from:send(msg.data)
        --msg.from:close()
        --tcphandlers[msg.clientid]='disconnect'
      elseif msg.cmd=='udpdata' then
        out('udp:'..msg.clientip..':'..msg.clientport..' '..msg.data)
        msg.from:sendto(msg.data,msg.clientip,msg.clientport)          
        --incudppkt()
        --concurrent.exit('master exit.')
      elseif msg.cmd=='close tcp' then
      
      elseif msg.cmd=='close udp' then
      
      elseif msg.cmd=='disconnect tcp client' then
      
      else
        error("*********************")      
      end
    end
  end

end

function monitor()
  local masterpid=concurrent.spawnmonitor(master)
  concurrent.register('master',masterpid)
  --concurrent.monitor('master')
  usocks={}
  while true do
          out'*'
    local msg=concurrent.receive(1000)
    --for k,v in pairs(usocks) do
    --  if not msg then print('/nudppkt:'..k:status()..'/n') end
    --end
    -- msg.signal=='EXIT' or
    if msg and (msg.signal=='DOWN') then
      out(msg.from..' exit:'..msg.reason..'./n')
      if usocks[msg.from] then
        usocks[msg.from]:close()
        usocks[msg.from]=nil
        collectgarbage('collect')
        out'gc'
      end
      concurrent.unregister('master')
      local masterpid=concurrent.spawnlink(master)
      concurrent.register('master',masterpid)
      concurrent.monitor('master')
    elseif msg and msg.cmd=='started' then
      out'receive a started msg./n'
      if msg.udpsock and msg.from then
        usocks[msg.from]=msg.udpsock
        out'monitor: saw a master./n'
      end
    end
   end
end
local monitorpid=concurrent.spawn(monitor)
concurrent.register('monitor',monitorpid)



--while true do
  -- main loop  
  --concurrent.step(0)-- noblock
  
  --out"."
  --cltime.sleep(1)  
  io.flush()
--end

concurrent.loop()


--return masterpid



抱歉!评论已关闭.