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的粘包问题,所以会存在一个固定大小的头。比如我们的头是:

?
1
2
3
4
5
6
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

今天先记录到此,后续如有需要再补充。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值