lua开发笔记

因为最近的项目需要,学习了lua编程,并使用lua进行网络相关的开发,在此记录一下用到的相关的知识。

在整个项目中,我只是负责其中的固件升级模块的开发,数据格式是自定义的,并没有采用Json或者是XML,主要是因为传输的字段比较少,而且不希望引入太多的第三方库。

一、LuaSocket

项目中,采用的是tcp通信,这里仅介绍tcp相关的知识。

1.首先需要加载socket模块:

local socket = require(‘socket‘)

如果要查看LuaSocket的版本:

print(‘LuaSocket ver: ‘, socket._VERSION)

2. tcp常用方法:

关于以下方法的说明,我觉得官方文档已经说得很清楚了,在此就直接引用官方说明:

1)socket.bind(address, port [, backlog])

创建一个tcp server object bind to (address, port), backlog是用于listen函数的。熟悉Linux下的socket编程,会觉得这些都很熟悉的。此函数返回一个tcp server object,如果失败返回nil。

2)server:accept()

Waits for a remote connection on the server object and returns a client object representing that connection.

3)client:getsockname() : 获取socket的ip与port

4)server:getpeername() : 获取对端的ip与port

5)client:receive([pattern [, prefix]])

    接收数据,pattern与lua file I/O format类似,取值有:

’*all‘, ’*a‘ : reads from the socket until the connection is closed. No end-of-line translation is performed;

‘*line‘, ‘*l‘ : reads a line of text from the socket. The line is terminated by a LF character (ASCII 10), optionally preceded by a CR character (ASCII 13). The CR and LF characters are not included in the returned line. In fact, all CR characters are ignored by the pattern. This is the default pattern;

number : causes the method to read a specified number of bytes from the socket.

If successful, the method returns the received pattern.

In case of error, the method returns nil followed by an error message which can be the string ‘closed‘ in case the connection was closed before the transmission was completed or the string ‘timeout‘ in case there was a timeout during the operation. Also, after the error message, the function returns the partial result of the transmission.

6) client:send(data [, i [, j]])

Sends data through client object.

Data is the string to be sent. The optional arguments i and j work exactly like the standard string.sub Lua function to allow the selection of a substring to be sent.

If successful, the method returns the index of the last byte within [i, j] that has been sent.

In case of error, the method returns nil, followed by an error message,followed by the index of the last byte within [i, j] that has been sent.

7) client:close() : Closes a TCP object.

   8)master:settimeout(value [, mode]

    Changes the timeout values for the object. By default, all I/O operations are blocking.

9) server:setoption(option [, value])

    Sets options for the TCP object. Options are only needed by low-level or time-critical applications.

如我们常用的:‘keepalive‘, ‘reuseaddr‘, ‘tcp-nodelay‘

11) master:connect(address, port) : 用于户客户端发起连接请求

下面的代码分别展示了tcp服务端与客户端的大致结构:

-- echo server
local socket = require(‘socket‘)

local serv = socket.bind(‘*‘, 8000) -- bind to any ip and 8000 port.
if not serv then
	print(‘bind error‘)
	os.exit(-1)
end

while true do
	print(‘begin accept‘)
	local client = serv:accept()
	if not client then
		print(‘accept failed‘)
		os.exit(-1)
	end

	local peer_ip, peer_port = client:getpeername()
	print(string.format(‘handle %s:%d request begin‘, peer_ip, peer_port))
	while true do
		local data, err = client:receive(‘*line‘) -- read one line data
		if not err then
		    print(‘data: ‘, data)
		    client:send(data) -- send data back to client
		else
		    print(‘err: ‘, err)
		    break
		end
	end
	client:close()
end
-- echo client

local socket = require(‘socket‘)

local client = socket.connect(‘localhost‘, 8000) -- connect to localhost:8000
if not client then
	print(‘connect failed‘)
	os.exit(-1)
end

while true do
    local data = io.read(‘*line‘)
    if not data then
        print(‘EOF‘)
        break
    end
    
    client:send(data)
    local resp, err, partial = client:receive()
    if not err then
        print(‘receive: ‘, resp)
    else
        print(‘err: ‘, err)
        break
    end
end
client:close()

二、Lua bit operation module

lua语言自身并没有提供位运算,要进行位运算,需要引入第三方module.

local bit = require(‘bit‘)

y = bit.band(x1 [,x2...]) : 按位与

y = bit.bor(x1 [,x2...]) : 按位或

y = bit.bxor(x1 [,x2...]) : 按位异或

y = bit.bnot(x) : 按位取反

y = bit.lshift(x, n) : 逻辑左移

y = bit.rshift(x, n) : 逻辑右移

y = bit.arshift(x, n) : 算术右移

因为我在项目中需要传递整数,需要把整数的低位在前,高位在后进行传输,所以需要用到移位运算。

三、 string模块使用到的一些方法

因为项目中的数据格式采用的是自定义的,为了解决tcp的粘包问题,所以会存在一个固定大小的头。比如我们的头是:

uin8_t head[4] ;
head[0] = 0xA5; // head frame
head[1] = 0x1l; // cmd_id
uint16_t len = 0x0010;
head[2] = len & 0xff; // low byte of len
head[3] = len >> 8; // hight byte of len

那么在Lua中,我们要怎么才能做到把上述的4个字节头发送出去呢?可以用如下的方法:string.char()

local len = 0x0010
local t = {0xA5, 0x1, bit.band(len, 0xff), bit.rshift(len, 8)}
local data = string.char(unpack(t))
client:send(data)

那么接收方,在收取到数据头时,需要怎么去解析呢? string.byte()

local req , err = client:receive(4)
if not err then
    local req_t = {string.byte(req, 1, -1)}
    local frame = req_t[1]
    local cmd_id = req_t[2]
    local len = req_t[3] + bit.lshift(req_t[4], 8)
    print(string.format(‘frame:%02x, cmd_id:%02x, len:%d‘, frame, cmd_id, len))
else
    print(‘err: ‘, err)
    client:close()
end

PS : 关于Lua编程的学习,可以参考《lua程序设计》这本书,还有一个博客lua step by step,内容也是根据此书写的,写的非常的好,http://www.cnblogs.com/stephen-liu74/archive/2012/07/30/2487201.html

今天先记录到此,后续如有需要再补充。

时间: 2024-11-05 14:25:16

lua开发笔记的相关文章

PHP微信公众开发笔记(三)

PHP微信公众开发笔记系列 日期:2014.9.2 今天主要的任务是昨天提到的那个处理缓存信息的问题,我需要保存一些消息用来做二次判断. 首先,记录一些PHP语法知识吧. 1.PHP中字符串的连接语法: 在lua中,两个字符串的连接很简单,加入有两个字符串 "aaa";"bbb"; 需要将这两个字符串连接起来,只需要用两个句点 .. 便可以了:"aaa" .. "bbb"; 这里要注意,字符串与句点直接需要有空格,没有空格会报

Lua学习笔记--环境配置&Hello World

最近发现要恶补的东西实在是太多了,DX还没学完,现在发现还要用Lua脚本语言,于是,我的笔记又加了一个系列,Lua学习笔记. 一.简介 Lua是一门小巧的脚本语言,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能.Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行.Lua并没有提供强大的库,这是由它的定位决定的.所以Lua不适合作为开发独立应用程序的语言. Lua脚本可以很容易的被C/C++ 代码调用,也可以反过来调用C/C++的函数,这使得Lua在应用程序

张高兴的 Windows 10 IoT 开发笔记:RTC 时钟模块 DS3231

原文:张高兴的 Windows 10 IoT 开发笔记:RTC 时钟模块 DS3231 GitHub:https://github.com/ZhangGaoxing/windows-iot-demo/tree/master/DS3231 注意:不包含闹钟设置

Android开发笔记(一百零三)地图与定位SDK

集成地图SDK 国内常用的地图SDK就是百度和高德了,二者的用法大同小异,可按照官网上的开发指南一步步来.下面是我在集成地图SDK时遇到的问题说明: 1.点击基本地图功能选项,不能打开地图,弹出"key验证出错!请在AndroidManifest.xml文件中检查key设置的"的红色字提示.查看日志提示"galaxy lib host missing meta-data,make sure you know the right way to integrate galaxy&

微信订阅号开发笔记(二)

微信开发的流程其实很简单 o(∩_∩)o 哈哈!在微信网站的编辑操作 额,就不说了.虽然有人问过.下面是我的微信开发过程,简单记录下. 成为开发者 材料:1.自己的服务器资源,百度的BAE,新浪的SAE都不错. 2.懂那么点编程语言. 3.注册微信公众号. 上面的都有了之后,就可以自己动手开发了.哇咔咔,好兴奋.有木有. 在登录进去之后,怎么成为开发者?不知道,自己看去. 开始coding吧. 1.验证 if (! empty ( $_GET ['echostr'] ) && ! empt

微信订阅号开发笔记(三)

1.接收语音识别结果 if($msgType=="voice"){ //收到语音消息 //MediaId 语音消息媒体id,可以调用多媒体文件下载接口拉取数据. //Format 语音格式,如amr,speex等 $format = $postObj->Format; $mediaId = $postObj->MediaId; //开通语音识别功能,用户每次发送语音给公众号时,微信会在推送的语音消息XML数据包中,增加一个Recongnition字段. //注:由于客户端缓

微信订阅号开发笔记(四)

1.创建菜单 //创建菜单 public function createMenu(){ $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token="; $url.=$this->getacctoken(); //目前自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单.一级菜单最多4个汉字, //二级菜单最多7个汉字,多出来的部分将会以"..."代替.请注意,创建自定义菜单

Swift开发笔记

Swift开发笔记(一) 刚开始接触XCode时,整个操作逻辑与Android Studio.Visual Studio等是完全不同的,因此本文围绕IOS中控件的设置.事件的注册来简单的了解IOS开发 1.新建一个Xcode项目,项目目录大致如图: 2.在Main.storyboard添加控件 首先要显示右侧的工具栏(Utilities),之后选择显示Object Library,就可以找到常用的一些控件了,然后添加几个控件到界面中 3.将控件和ViewController进行关联 此时要将Ed

张高兴的 Xamarin.Forms 开发笔记:为 Android 与 iOS 引入 UWP 风格的汉堡菜单 ( MasterDetailPage )

所谓 UWP 样式的汉堡菜单,我曾在"张高兴的 UWP 开发笔记:汉堡菜单进阶"里说过,也就是使用 Segoe MDL2 Assets 字体作为左侧 Icon,并且左侧使用填充颜色的矩形用来表示 ListView 的选中.如下图 但怎样通过 Xamarin.Forms ,将这一样式的汉堡菜单带入到 Android 与 iOS 中呢? 一.大纲-细节模式简介 讲代码前首先来说说这种导航模式,官方称"大纲-细节模式"(MasterDetail).左侧的汉堡菜单称为&qu