加载中…
正文 字体大小:

Luat实例教程:tcp短连接_飞行模式

(2018-03-25 07:47:14)
分类: GPRS模块

本示例实现的功能是:基于TCP的socket短连接通信demo项目,会进入飞行模式并且定时退出飞行模式(UDP使用方式和TCP完全相同)。此例子为短连接,发送数据后,进入飞行模式,然后定时退出飞行模式再发送数据,如此循环

功能描述:

1、连接后台发送位置包"loc data\r\n"到后台,超时时间为2分钟,2分钟内如果失败,会一直重试,发送成功或者超时后都进入飞行模式;

2、进入飞行模式5分钟后,退出飞行模式,然后继续第1步
循环以上2个步骤

2、收到后台的数据时,在rcv函数中打印出来

测试时请搭建自己的服务器,并且修改下面的PROT,ADDR,PORT,支持域名和IP地址

1.在编辑工具建立一个test.lua的文件(不一定叫这个名字,用户可以自己随便取名)

2.设置本文件被全体可见。也就意味着,一旦test被某一文件加载,则test在任何文件中均可被看见,即test中全局变量和函数均可被任何文件调用。


module(...,package.seeall)

3.test文件头需要 require "xxx" 模块。加载后,就可以调用xxx.lua库文件中的全局变量和函数了


require"socket"

4.定义print函数,调试用


local function print(...)
    _G.print("test",...)
end

5.定义相关参数


local ssub,schar,smatch,sbyte,slen = string.sub,string.char,string.match,string.byte,string.len
--测试时请搭建自己的服务器
local SCK_IDX,PROT,ADDR,PORT = 1,"TCP","120.26.196.195",9999
--每次连接后台,会有如下异常处理
--一个连接周期内的动作:如果连接后台失败,会尝试重连,重连间隔为RECONN_PERIOD秒,最多重连RECONN_MAX_CNT次
--如果一个连接周期内都没有连接成功,则等待RECONN_CYCLE_PERIOD秒后,重新发起一个连接周期
--如果连续RECONN_CYCLE_MAX_CNT次的连接周期都没有连接成功,则重启软件
local RECONN_MAX_CNT,RECONN_PERIOD,RECONN_CYCLE_MAX_CNT,RECONN_CYCLE_PERIOD = 3,5,1,20
--reconncnt:当前连接周期内,已经重连的次数
--reconncyclecnt:连续多少个连接周期,都没有连接成功
--一旦连接成功,都会复位这两个标记
--conning:是否在尝试连接
local reconncnt,reconncyclecnt,conning = 0,0

6.连接成功,编写socket处理函数。


--[[
函数名:ntfy
功能  :socket状态的处理函数
参数  :
        idx:number类型,socket.lua中维护的socket idx,跟调用socket.connect时传入的第一个参数相同,程序可以忽略不处理
        evt:string类型,消息事件类型
        result: bool类型,消息事件结果,true为成功,其他为失败
        item:table类型,{data=,para=},消息回传的参数和数据,目前只是在SEND类型的事件中用到了此参数,例如调用socket.send时传入的第2个和第3个参数分别为dat和par,则item={data=dat,para=par}
返回值:无
]]
function ntfy(idx,evt,result,item)
    print("ntfy",evt,result,item)
    --连接结果(调用socket.connect后的异步事件)
    if evt == "CONNECT" then
        conning = false
        --连接成功
        if result then
            reconncnt,reconncyclecnt = 0,0
            --停止重连定时器
            sys.timer_stop(reconn)          
            --发送位置包到后台
            locrpt()
        --连接失败
        else
            --RECONN_PERIOD秒后重连
            sys.timer_start(reconn,RECONN_PERIOD*1000)
        end 
    --数据发送结果(调用socket.send后的异步事件)
    elseif evt == "SEND" then
        if item then
            sndcb(item,result)
        end
    --连接被动断开
    elseif evt == "STATE" and result == "CLOSED" then
        --补充自定义功能代码
    --连接主动断开(调用link.shut后的异步事件)
    elseif evt == "STATE" and result == "SHUTED" then
        --补充自定义功能代码
    --连接主动断开(调用socket.disconnect后的异步事件)
    elseif evt == "DISCONNECT" then
        --补充自定义功能代码         
    end
    --其他错误处理
    if smatch((type(result)=="string") and result or "","ERROR") then
        --断开数据链路,重新激活
        link.shut()
    end
end

--[[
函数名:rcv
功能  :socket接收数据的处理函数
参数  :
        idx :socket.lua中维护的socket idx,跟调用socket.connect时传入的第一个参数相同,程序可以忽略不处理
        data:接收到的数据
返回值:无
]]
function rcv(idx,data)
    print("rcv",data)
end

7.发送数据后,进入飞行模式,然后定时退出飞行模式再发送数据,如此循环。


--[[
函数名:snd
功能  :调用发送接口发送数据
参数  :
        data:发送的数据,在发送结果事件处理函数ntfy中,会赋值到item.data中
        para:发送的参数,在发送结果事件处理函数ntfy中,会赋值到item.para中 
返回值:调用发送接口的结果(并不是数据发送是否成功的结果,数据发送是否成功的结果在ntfy中的SEND事件中通知),true为成功,其他为失败
]]
function snd(data,para)
    return socket.send(SCK_IDX,data,para)
end


--[[
函数名:locrptimeout
功能  :位置包数据发送超时处理,直接进入飞行模式
参数  :无  
返回值:无
]]
local function locrptimeout()
    print("locrptimeout")
    locrptcb(true)
end

--[[
函数名:locrpt
功能  :发送位置包数据到后台
参数  :无 
返回值:无
]]
function locrpt()
    print("locrpt") 
    --调用发送接口成功,并不是数据发送成功,数据发送是否成功,在ntfy中的SEND事件中通知
    if snd("loc data\r\n","LOCRPT") then
        --设置2分钟定时器,如果超时2分钟数据都没有发送成功,则直接进入飞行模式
        sys.timer_start(locrptimeout,120000)
    --调用发送接口失败,做重连处理
    else
        locrptcb()
    end 
end

--[[
函数名:locrptcb
功能  :位置包发送结果处理,发送成功或者超时,都会进入飞行模式,启动5分钟的“退出飞行模式,连接后台”定时器
参数  :  
        result: bool类型,发送结果或者是否超时,true为成功或者超时,其他为失败
        item:table类型,{data=,para=},消息回传的参数和数据,例如调用socket.send时传入的第2个和第3个参数分别为dat和par,则item={data=dat,para=par}
返回值:无
]]
function locrptcb(result,item)
    print("locrptcb",result)
    if result then
        socket.disconnect(SCK_IDX)
        link.shut()
        misc.setflymode(true)
        sys.timer_start(connect,300000)
        sys.timer_stop(locrptimeout)
    else
        sys.timer_start(reconn,RECONN_PERIOD*1000)
    end
end

--[[
函数名:sndcb
功能  :发送数据结果事件的处理
参数  :  
        result: bool类型,消息事件结果,true为成功,其他为失败
        item:table类型,{data=,para=},消息回传的参数和数据,例如调用socket.send时传入的第2个和第3个参数分别为dat和par,则item={data=dat,para=par}
返回值:无
]]
local function sndcb(item,result)
    print("sndcb",item.para,result)
    if not item.para then return end
    if item.para=="LOCRPT" then
        locrptcb(result,item)
    end 
end

8.断线自动重连


--[[
函数名:reconn
功能  :重连后台处理
        一个连接周期内的动作:如果连接后台失败,会尝试重连,重连间隔为RECONN_PERIOD秒,最多重连RECONN_MAX_CNT次
        如果一个连接周期内都没有连接成功,则等待RECONN_CYCLE_PERIOD秒后,重新发起一个连接周期
        如果连续RECONN_CYCLE_MAX_CNT次的连接周期都没有连接成功,则重启软件
参数  :无
返回值:无
]]
function reconn()
    print("reconn",reconncnt,conning,reconncyclecnt)
    --conning表示正在尝试连接后台,一定要判断此变量,否则有可能发起不必要的重连,导致reconncnt增加,实际的重连次数减少
    if conning then return end
    --一个连接周期内的重连
    if reconncnt < RECONN_MAX_CNT then      
        reconncnt = reconncnt+1
        link.shut()
        connect()
    --一个连接周期的重连都失败
    else
        reconncnt,reconncyclecnt = 0,reconncyclecnt+1
        if reconncyclecnt >= RECONN_CYCLE_MAX_CNT then
            dbg.restart("connect fail")
        end
        sys.timer_start(reconn,RECONN_CYCLE_PERIOD*1000)
    end
end

9.定时器启动connect()函数


sys.timer_start(connect,2000)

10.在编辑工具中建立一个名为main.lua的文件。lua脚本的执行从main.lua开始,main.lua是入口文件(注意:main.lua只能有一个)。在main.lua中把test加载进去就好了。sys.init()是对系统初始化,sys.run()是系统主程序。这两句必须有。


--重要提醒:必须在这个位置定义MODULE_TYPE、PROJECT和VERSION变量
--MODULE_TYPE:模块型号,目前仅支持Air201、Air202、Air800
--PROJECT:ascii string类型,可以随便定义,只要不使用,就行
--VERSION:ascii string类型,如果使用Luat物联云平台固件升级的功能,必须按照"X.X.X"定义,X表示1位数字;否则可随便定义
MODULE_TYPE = "Air202"
PROJECT = "SOCKET_SHORT_CONNECTION_FLYMODE"
VERSION = "1.0.0"
require"sys"
require"test"
if MODULE_TYPE=="Air201" then
require"wdt"
end
sys.init(0,0)
sys.run()

!!!attention


一个工程只有一个main.lua


0

阅读 评论 收藏 转载 喜欢 打印举报
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有