• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

跨平台高效率Lua网络库(同步形式的API,底层是异步非阻塞)

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

项目地址: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 examples\PingpongServer.lua,然后执行 Joynet examples\PingpongClient.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("\r\n")

					--读取多行头部
					while true do
						packet = session:receiveUntil("\r\n")
						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\r\nConnection: close\r\nContent-Type: text/html\r\nContent-Length: "..string.len(htmlBody).."\r\n\r\n"..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

  


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
深入理解Lua虚拟机发布时间:2022-07-22
下一篇:
使用Redis存储聊天数据的一种方案(使用lua解决原子性问题)发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap