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

本文介绍了一个使用Lua编写的并发程序示例,通过Copas和Concurrent库实现了TCP和UDP服务监听,并展示了如何处理客户端连接及数据接收。文章深入探讨了Lua在实际网络应用中的并发处理技巧。

<meta content="Vim/7.1" name="Generator" id="d3m50"> <meta content="text/html; charset=GBK" http-equiv="content-type" id="d3m51"> require'concurrent'
require'cltime'
require'socket'

concurrent.setoption('trapexit',true)

localout=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'
localtcphandlers={}
localfunctiontcphandler(sock)
clientip,clientport=sock:getpeername()
sock=copas.wrap(sock)
sock:settimeout(0)

clientid=clientip..':'..clientport
tcphandlers[clientid]='connected'

whiletruedo
localdata=sock:receive("*l")-- receive a line
--if tcphandlers[clientid]=='connected' then
ifdata 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


localudpinit=function(port)
localu=socket.udp()
collectgarbage('collect')
u:settimeout(0)
--u:setoption('reuseaddr',true)
ret,err=u:setsockname("*",port)
ifnotretthen
out('bind error:'..err)
concurrent.exit('port:'..port..' bind error.')
end
out('udp listening at '..port..'/n')
out'/n'
returnu;
end
localfunctionudpfini(udpsock)
udpsock:close()
end
localudpstep=function(udpsock)
localdata,ip,port=udpsock:receivefrom(1024)

ifdata 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!!!!!!!!!!!!!!!!!!!!!!!!
localmaster=function()
out"master inited./n"
selfpid=concurrent.whereis('master')
out('selfpid:'..selfpid)
localudplistener={}
localtcplistener={}

localudpsock=udpinit(port)

ifnotudpsock thenconcurrent.exit('udp init failed.') end

concurrent.send('monitor',{from=selfpid,cmd='started',['udpsock']=udpsock})
whiletruedo
out'#'
copas.step(0.1)-- noblock
udpstep(udpsock)
localmsg=concurrent.receive(100) -- timeout
--if not msg then out'master timeout/n'; end
--io.flush()
ifmsg then
ifmsg.cmd=='new udp'then

elseifmsg.cmd=='accept tcp'then

elseifmsg.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'
elseifmsg.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.')
elseifmsg.cmd=='close tcp'then

elseifmsg.cmd=='close udp'then

elseifmsg.cmd=='disconnect tcp client'then

else
error("*********************")
end
end
end

end

functionmonitor()
localmasterpid=concurrent.spawnmonitor(master)
concurrent.register('master',masterpid)
--concurrent.monitor('master')
usocks={}
whiletruedo
out'*'
localmsg=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
ifmsg and(msg.signal=='DOWN') then
out(msg.from..' exit:'..msg.reason..'./n')
ifusocks[msg.from] then
usocks[msg.from]:close()
usocks[msg.from]=nil
collectgarbage('collect')
out'gc'
end
concurrent.unregister('master')
localmasterpid=concurrent.spawnlink(master)
concurrent.register('master',masterpid)
concurrent.monitor('master')
elseifmsg andmsg.cmd=='started'then
out'receive a started msg./n'
ifmsg.udpsock andmsg.from then
usocks[msg.from]=msg.udpsock
out'monitor: saw a master./n'
end
end
end
end
localmonitorpid=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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值