跨平台高效率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 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

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM