zoukankan      html  css  js  c++  java
  • 跨平台高效率Lua网络库 ( 同步形式的API ,底层是异步非阻塞)

    Joynet

    项目地址:https://github.com/IronsDu/Joynet

    介绍

    high performance network library for lua, based on https://github.com/IronsDu/accumulation-dev and lua coroutine. Joynet 的网络底层使用多线程,但Lua (层面)是运行在单线程上。

    借助协程提供同步形式的API。(同步的socket api,同步的http api,同步的redis api)

    让应用业务开发更轻松,更爽!

    src 目录是此项目源代码, libs 目录为基于此Lua协程网络库开发的一些库

    构建

    • Windows : 在项目根目录中打开 Joynet.sln, 编译即可在当前目录产生可执行文件 Joynet
    • Linux : 在项目根本执行 make 即可生成可执行文件 Joynet

    使用

    examples 包含测试代码。 譬如我们要在Windows下运行PingPong测试: 先在项目根目录执行 Joynet examplesPingpongServer.lua,然后执行 Joynet examplesPingpongClient.lua

    一个小问题

    当前Joynet是作为一个宿主程序,由其运行业务Lua文件。 不过我们能轻松的把它作为动态库集成到已有的应用系统里。

    关于协程

    协程是轻量级线程,所以多线程有的问题它也有,只是影响程度不同。 在协程中使用同步API会阻塞当前协程,所以当你的应用程序只有一个协程从外部收取网络消息时,且在消息处理中使用同步API 操作Redis或者Http的话,效率会很低。 这时有两个方案可解决:1 、提供回调形式的异步API, 但这样会使开发概念混乱 ; 2、 在前面说到的情景的消息处理中开启协程,并在其中操作HTTP/Redis,而不是直接在消息处理所在协程中进行操作。 (当然,协程的创建和切换有一定开销,所以~看着办吧 ^-^ )

    例子:

    PingpongServer.lua:

    package.path = "./src/?.lua;./libs/?.lua;"
    
    local TcpService = require "TcpService"
    local AcyncConnect = require "Connect"
    
    local totalRecvNum = 0
    
    function userMain()
    
    	--开启服务器
    	local serverService = TcpService:New()
    	serverService:listen("0.0.0.0", 9999)
    
    	coroutine_start(function()
    		while true do
    			local session = serverService:accept()
    			if session ~= nil then
    				coroutine_start(function ()
    					local strLen = 5		--读取5个字节
    					while true do
    						local packet = session:receive(strLen)
    						if packet ~= nil then
    							totalRecvNum = totalRecvNum + 1
    							session:send(packet)
    						end
    						if session:isClose() then
    							break
    						end
    					end
    				end)
    			end
    		end
    	end)
    
    	coroutine_start(function ()
    			while true do
    				coroutine_sleep(coroutine_running(), 1000)
    				print("total recv :"..totalRecvNum.."/s")
    				totalRecvNum = 0
    			end
    		end)
    end
    
    coroutine_start(function ()
    	userMain()
    end)
    
    while true
    do
    	CoreDD:loop()
    	while coroutine_pengdingnum() > 0
    	do
    		coroutine_schedule()
    	end
    end
    

      PingPongClient.lua:

    package.path = "./src/?.lua;./libs/?.lua;"
    
    local TcpService = require "TcpService"
    local AcyncConnect = require "Connect"
    
    local totalRecvNum = 0
    
    function userMain()
    
    	--开启10个客户端
    	local clientService = TcpService:New()
    	clientService:createService()
    		
    	for i=1,1 do
    		coroutine_start(function ()
    			local session = clientService:connect("127.0.0.1", 9999, 5000)
    
    			if session ~= nil then
    				local str = "hello"
    				local strLen = string.len(str)
    
    				session:send(str)
    				while true do
    				local packet = session:receive(strLen)
    					if packet ~= nil then
    						totalRecvNum = totalRecvNum + 1
    						session:send(packet)
    					end
    
    					if session:isClose() then
    						break
    					end
    				end
    			else
    				print("connect failed")
    			end
    		end)
    	end
    
    	coroutine_start(function ()
    			while true do
    				coroutine_sleep(coroutine_running(), 1000)
    				print("total recv :"..totalRecvNum.."/s")
    				totalRecvNum = 0
    			end
    		end)
    end
    
    coroutine_start(function ()
    	userMain()
    end)
    
    while true
    do
    	CoreDD:loop()
    	while coroutine_pengdingnum() > 0
    	do
    		coroutine_schedule()
    	end
    end
    

      

    Http Server :

    package.path = "./src/?.lua;./libs/?.lua;"
    
    local TcpService = require "TcpService"
    
    local totalRecvNum = 0
    
    function userMain()
    	if true then
    	--开启http服务器
    	local serverService = TcpService:New()
    	serverService:listen("0.0.0.0", 80)
    	coroutine_start(function()
    		while true do
    			local session = serverService:accept()
    			if session ~= nil then
    				coroutine_start(function ()
    
    					--读取报文头
    					local packet = session:receiveUntil("
    ")
    
    					--读取多行头部
    					while true do
    						packet = session:receiveUntil("
    ")
    						if packet ~= nil then
    							if #packet == 0 then
    								--print("recv empty line")
    								break
    							end
    						end
    					end
    
    					local htmlBody = "<html><head><title>This is title</title></head><body>hahaha</body></html>"
    					local response = "HTTP/1.1 200 OK
    Connection: close
    Content-Type: text/html
    Content-Length: "..string.len(htmlBody).."
    
    "..htmlBody
    
    					session:send(response)
    
    					totalRecvNum = totalRecvNum + 1
    				end)
    			end
    		end
    	end)
    
    	coroutine_start(function ()
    			while true do
    				coroutine_sleep(coroutine_running(), 1000)
    				print("total recv :"..totalRecvNum.."/s")
    				totalRecvNum = 0
    			end
    		end)
    end
    
    coroutine_start(function ()
    	userMain()
    end)
    
    while true
    do
    	CoreDD:loop()
    	while coroutine_pengdingnum() > 0
    	do
    		coroutine_schedule()
    	end
    end
    

      

  • 相关阅读:
    gradle使用笔记
    MaxScale初探
    mariadb-10GTID复制及多源复制
    Shell中的循环语句实例
    Failed to load slave replication state from table mysql.gtid_slave_pos: 1146: Table 'mysql.gtid_slave_pos' doesn't exist
    学习MongoDB--(5-2):索引(查看索引的使用,管理索引)
    MongoDB索引管理
    mysql 5.5与5.6 timestamp 字段 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP的区别
    MongoDB增加用户、删除用户、修改用户读写权限及只读权限(注:转载于http://www.2cto.com/database/201203/125025.html)
    MongoDB创建数据库
  • 原文地址:https://www.cnblogs.com/irons/p/5549147.html
Copyright © 2011-2022 走看看