跨平台高效率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
跨平台高效率Lua网络库 ( 同步形式的API ,底层是异步非阻塞)的更多相关文章
- Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO
Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO Java 非阻塞 IO 和异步 IO 转自https://www.javadoop.com/post/nio-and-aio 本系 ...
- java的高并发IO原理,阻塞BIO同步非阻塞NIO,异步非阻塞AIO
原文地址: IO读写的基础原理 大家知道,用户程序进行IO的读写,依赖于底层的IO读写,基本上会用到底层的read&write两大系统调用.在不同的操作系统中,IO读写的系统调用的名称可能不完 ...
- [INet] I/O模型:同步阻塞,同步非阻塞,异步非阻塞
POSIX 把这同步.异步两个术语定义 如下: 同步 I/O 操作( synchronous I/O opetation) 导致请求进程阻塞, 直到 I/O 操作完成: 异步 I/O 操作( asyn ...
- [Boost基础]并发编程——asio网络库——同步socket处理
网络通信简述 asio库支持TCP,UDP和ICMP通信协议,它在名字空间boost::asio::ip里提供了大量的网络通信方面的函数和类,很好的封装了原始的Berkeley Socket API, ...
- 阻塞I/O、非阻塞I/O和I/O多路复用、怎样理解阻塞非阻塞与同步异步的区别?
“阻塞”与"非阻塞"与"同步"与“异步"不能简单的从字面理解,提供一个从分布式系统角度的回答.1.同步与异步 同步和异步关注的是消息通信机制 (syn ...
- 简明网络I/O模型---同步异步阻塞非阻塞之惑
转自:http://www.jianshu.com/p/55eb83d60ab1 网络I/O模型 人多了,就会有问题.web刚出现的时候,光顾的人很少.近年来网络应用规模逐渐扩大,应用的架构也需要随之 ...
- 网络I/O模型---同步异步阻塞非阻塞之惑
网络I/O模型 人多了,就会有问题.web刚出现的时候,光顾的人很少.近年来网络应用规模逐渐扩大,应用的架构也需要随之改变.C10k的问题,让工程师们需要思考服务的性能与应用的并发能力. 网络应用需要 ...
- python网络编程基础(线程与进程、并行与并发、同步与异步、阻塞与非阻塞、CPU密集型与IO密集型)
python网络编程基础(线程与进程.并行与并发.同步与异步.阻塞与非阻塞.CPU密集型与IO密集型) 目录 线程与进程 并行与并发 同步与异步 阻塞与非阻塞 CPU密集型与IO密集型 线程与进程 进 ...
- 谈谈对不同I/O模型的理解 (阻塞/非阻塞IO,同步/异步IO)
一.关于I/O模型的问题 最近通过对ucore操作系统的学习,让我打开了操作系统内核这一黑盒子,与之前所学知识结合起来,解答了长久以来困扰我的关于I/O的一些问题. 1. 为什么redis能以单工作线 ...
随机推荐
- (转载)Java里快如闪电的线程间通讯
转自(http://www.infoq.com/cn/articles/High-Performance-Java-Inter-Thread-Communications) 这个故事源自一个很简单的想 ...
- Labview二进制文件的操作
- 创建一个EMS 扩展包
EMS Package 向导: File > New > Other > Delphi projects > EMS > EMS Package Empty packag ...
- CTE初识
微软从SQl2005起引入了CTE(Common Table Expression)以强化T-SQL.这是一个类似于非持久视图的好东西. 正常的SQL语句: select * from person. ...
- MFC下的各种字符串类型和相互转换
MFC下的常用字符串数据类型表示的含义: L:Long 长 P:Point 指针 C:Const 常量 W:Wchar_t 宽字符 T:TCHAR STR:String 字符串 在看看MF ...
- Pongo建立信号基站-实际上还是考中位数
题目: 要建立一个信号基站服务n个村庄,这n个村庄用平面上的n个点表示.假设基站建立的位置在(X,Y),则它对某个村庄(x,y)的距离为max{|X – x|, |Y – y|}, 其中| |表示绝对 ...
- JS、jqueryie6浏览器下使用js无法提交表单的解决办法
-----------------------JS.jqueryie6浏览器下使用js无法提交表单的解决办法---------------------------------------------- ...
- Giraph之SSSP(shortest path)单机伪分布运行成功
所遇问题:Exception 1: Exception in thread "main" java.lang.IllegalArgumentException: "che ...
- Unity3d:延迟加载ScrollView的内容
问题描述:在一个scrollview中加载了大量的数据,有文字.图片.视频等等,首次加载的时候会很慢很卡,而且加载出来后,内存占用很大.解决方案1:思:固定一块区域,当物体滚动到这区域的时候再加载物体 ...
- Maven仓库的布局
任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存储路径,这便是Maven的仓库布局方式.例如log4j:log4j:1.2.15这一依赖,其对应的仓库路径为log4j/log4j/ ...