zoukankan      html  css  js  c++  java
  • Lua学习笔记

    Lua学习笔记
     
    
    目录
    Lua学习笔记    1
    需求    2
    选型    2
    Python    2
    Lua    3
    分析    4
    环境    4
    下载所需依赖    4
    环境配置    4
    代码    5
    代码结构如下    5
    Monster.java    5
    LuaDemo.java    7
    MyMonsterThread.java    8
    LuaTest.java    9
    demo.lua    13
    问题    18
    总结    19
    
    需求
    在游戏开发过程中,由于需要支持不同的手机平台,如winPhone、android、iphone等,这样,一套游戏逻辑就需要重新开发多次,而这部分游戏逻辑是与平台无关的,可以单独实现,如果这部分逻辑提炼出来,嵌入到不同的语言中,将会使得维护起来更加方便;
    另外,服务器后台在处理游戏逻辑的时候,同样会出现游戏逻辑经常出现变化的情况,比如任务系统的更新等,这样,如果游戏逻辑直接写到code中,会造成每次更新都需要重启服务的情况,我们希望实现热更新,尤其是业务逻辑模块方面的变化,当出现多服的情况下,这部分的更新会更麻烦;
    还有就是游戏设计师与程序员沟通的问题,当设计师设计出一套场景后,需要程序员去实现才能看到具体的结果,沟通费时费力还不一定达到预期的效果,如果出现一种脚本语言使得设计师不需要依赖程序员即可独立设计并表现出游戏场景,同时设计师与程序员都熟悉这种脚本语言,则对双方都受益。
    
    选型
    市面上出现的适合于游戏开发的脚本语言主要有Python与Lua,因为这两种脚本语言都可以直接调用C++功能(虽然我是一个java程序员,但不得不承认,绝大部分的好玩的大型游戏都是基于C++实现的),事实上,这两种脚本语言的兼容性与扩展性都非常好(都可以集成到Java中)
    
    关于Python与Lua的对比(http://lua-users.org/wiki/LuaVersusPython)
    Python
    扩展模块更加完善。含有大量的有用的函数库,非常利于线下工作,如作为工具脚本。另外还有大量的教程。
    通过附加模块可实现极为出色的多维数组数值计算能力(个人认为在做机器学习算法等数学模型应用中可能会更合适),严格的说,Lua并没有数组的概念,所有的数据结构都是以table形式存储的。
    自带ctypes数据类型。可以访问动态链接库(.so文件或.dll文件),无需对C进行扩展。、
    支持远程调试。
    Lua有一个简约的不能再简单的语法,这点上与Python没有较大差别。
    Python对string与list做了较大层度的扩展,我建议如果想要在Lua中更有成效,就去使用扩展库
    
    Python对Unicode编码的支持更好些
    Python对空白字符敏感
    Python内置了按位操作,Lua可通过扩展库实现
    Python具有错误检测能力,而在这方面,Lua更易出错
    Python有更为详细的初学者文档,目前尚缺乏对Lua介绍的入门教程
     
    Lua
    Lua比Python小巧的多,python22.dll 824KB,而一个基本的lua引擎仅在100KB以下
    占用内存更少
    看起来没有任何的指针使用
    编译器与解释器执行起来更快
    在脚本与C语言中,仅用少量的"胶水代码"即可实现较为优雅且简单的API交互
    不适用可以得到复杂而易出错对象的引用计数
    Lua以作为一门配置语言开始,在需要创建与配置文件的时候(尤其是在游戏中),他是非常了不起的
    Lua有一个非常漂亮且简单强大的语法,与Python相比,可以用更少的代码
    Lua有一个小巧简单稳定的代码库,如果需要,查看与修改很容易,但可能文档不如Python完善
    
    Lua很少有扩展组件使之更易为一个专门的需要做绑定,Python则需要众多的模块
    Lua支持多线程操作,多个解释器可以同存于一个进程中,每一个解释器都可以在自己的线程中独立运行,因此,Lua更适合在多线程程序中嵌入
    Lua对空白字符不敏感
    Lua支持多线程开箱即用,可在一个单独的线程或进程中有多个解释器,而Python不支持多线程,多线程可以访问解释器,但需要每个线程都必须持有全局锁
    
    分析
    通过以上分析,在做独立的运行程序或脚本时候,采用Python是一个不错的选择(如线下分析等任务),而作为脚本嵌入到另外一种语言中,更推荐使用Lua
    环境
    下载所需依赖
    Win32:
    Win64 :
    其他环境:下载地址:http://www.keplerproject.org/luajava/index.html#download
    
    源码以及文档:
    教程:
    环境配置
    将luajava-1.1.dll加入到jre的bin目录下
    将luajava-1.1.jar引入到工程的环境变量中
    下载lua的eclipse插件Lua Development Tools
    如需单独调试Lua,则需要单独安装LuaForWindows 编译器
    代码
    代码结构如下
    Monster.java
    package com.chilijoy.bean;
    import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
    /*******************************************************************************
    *
    * Monster.java Created on 2014年7月28日
    *
    * Author: linfenliang
    *
    * Description:
    *
    * Version: 1.0
    ******************************************************************************/
    public class Monster {
        private String race;//种族
        private int defense;//防御值
        private int attack;//攻击值
        private int life;//生命值
        public String getRace() {
            return race;
        }
        public void setRace(String race) {
            this.race = race;
        }
        public int getDefense() {
            return defense;
        }
        public void setDefense(int defense) {
            this.defense = defense;
        }
        public int getAttack() {
            return attack;
        }
        public void setAttack(int attack) {
            this.attack = attack;
        }
        public int getLife() {
            return life;
        }
        public void setLife(int life) {
            this.life = life;
        }
        @Override
        public String toString() {
            return ReflectionToStringBuilder.toString(this);
        }
    }
    
    LuaDemo.java
    package com.chilijoy.lua;
    import java.io.File;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    /*******************************************************************************
    *
    * LuaDemo.java Created on 2014年7月28日
    *
    * Author: linfenliang
    *
    * Description:
    *
    * Version: 1.0
    ******************************************************************************/
    public class LuaDemo {
        public static final String luaPath = "." + File.separator + "conf" + File.separator ;
        public static void main(String[] args) {
    
            ExecutorService service = Executors.newSingleThreadExecutor();
    
            for(int i=0;i<500000;i++){
                service.execute(new MyMonsterThread());
            }
            service.shutdown();
        }
    }
    
    MyMonsterThread.java
    package com.chilijoy.lua;
    import java.io.File;
    import org.keplerproject.luajava.LuaState;
    import org.keplerproject.luajava.LuaStateFactory;
    import com.chilijoy.bean.Monster;
    /*******************************************************************************
    *
    * MyMonster.java Created on 2014年7月28日
    *
    * Author: linfenliang
    *
    * Description:设计存在多次打开关闭问题,弃用
    *
    * Version: 1.0
    ******************************************************************************/
     
    public class MyMonsterThread extends Thread {
        static final String luaPath = "." + File.separator + "conf" + File.separator + demo.lua";
     
        @Override
        public void run() {
            LuaState lua = null;
            try {
                Monster m = new Monster();
                // System.out.println("monster_before:" + m);
                lua = LuaStateFactory.newLuaState();
                lua.openLibs();
                lua.LdoFile(luaPath);
                lua.getField(LuaState.LUA_GLOBALSINDEX, "create");
                // lua.pushObjectValue(monster);
                lua.pushJavaObject(m);
                lua.call(1, 0);
                // System.out.println("monster_after:" + m);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (lua != null) {
                    lua.close();
                }
                System.out.println(this.getName());
            }
        }
    }
     
     
    LuaTest.java
     
     
    package com.chilejoy.lua;
     
     
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
     
    import org.junit.Assert;
    import org.junit.Test;
    import org.keplerproject.luajava.LuaException;
    import org.keplerproject.luajava.LuaObject;
    import org.keplerproject.luajava.LuaState;
    import org.keplerproject.luajava.LuaStateFactory;
     
    import com.chilijoy.bean.Monster;
    import com.chilijoy.lua.LuaDemo;
    import com.chilijoy.lua.MyMonsterThread;
     
    /*******************************************************************************
     
    * LuaTest.java Created on 2014年7月28日
     
    * Author: linfenliang
     
    * Description:
     
    * Version: 1.0
     
    ******************************************************************************/
     
    public class LuaTest {
        static final int cycleTimes = 1000;
        @Test
        public void test() throws LuaException {
            System.out.println("-------input object test-------");
            LuaState lua = null;
            Monster m = new Monster();
            System.out.println("monster_before:" + m);
            lua = LuaStateFactory.newLuaState();
            lua.openLibs();
            lua.LdoFile(LuaDemo.luaPath + "demo.lua");
            lua.getField(LuaState.LUA_GLOBALSINDEX, "create");
            // lua.pushObjectValue(monster);
            lua.pushJavaObject(m);
            lua.call(1, 1);//传入一个参数,传出1个参数
            lua.setField(LuaState.LUA_GLOBALSINDEX, "monster");
            LuaObject obj = lua.getLuaObject("monster");
            System.out.println("monster_lua:"+obj.getObject());
            System.out.println("monster_after:" + m);
            Assert.assertEquals(obj.getObject(), m);
            lua.close();
        }
        @Test
        public void testHelloWorld(){
            System.out.println("-------hello ,world test-------");
            LuaState lua = LuaStateFactory.newLuaState();
            lua.openLibs();
            lua.LdoFile(LuaDemo.luaPath + "demo.lua");
            lua.getField(LuaState.LUA_GLOBALSINDEX, "hello");
            lua.call(0, 0);
            lua.close();
        }
        @Test
        public void calculateTest(){
            
            System.out.println("--------calculate---------");
            LuaState lua = null;
            lua = LuaStateFactory.newLuaState();
            lua.openLibs();
            lua.LdoFile(LuaDemo.luaPath + "demo.lua");
            lua.getField(LuaState.LUA_GLOBALSINDEX, "calculate");
            lua.pushNumber(3);
            lua.pushNumber(5);
            lua.pushNumber(8);
            lua.call(3, 1);
    //        lua.setField(LuaState.LUA_GLOBALSINDEX, "result");
    //        LuaObject obj = lua.getLuaObject("result");
            LuaObject obj = lua.getLuaObject(1);
            System.out.println("calculate result:"+obj.getNumber());
            lua.close();
        }
        @Test
        public void multipleReturnValueTest(){
            System.out.println("--------multipleReturnValue---------");
            LuaState lua = null;
            lua = LuaStateFactory.newLuaState();
            lua.openLibs();
            lua.LdoFile(LuaDemo.luaPath + "demo.lua");
            
            lua.getField(LuaState.LUA_GLOBALSINDEX, "getValues");
            lua.pushNumber(3);
            lua.pushNumber(5);
            lua.pushNumber(8);
            lua.call(3, 3);
            for(int i=1;i<=3;i++){
                LuaObject o1 = lua.getLuaObject(i);
                System.out.println("获取第"+i+"个返回值:"+o1.getNumber());
            }
            
            lua.close();
        }
        @Test
        public void nestedFuncTest(){
            System.out.println("------------nestedFunc-----------");
            LuaState state = LuaStateFactory.newLuaState();
            state.openLibs();
            state.LdoFile(LuaDemo.luaPath+"demo.lua");
            
            state.getField(LuaState.LUA_GLOBALSINDEX, "nestedFunc");
            state.pushNumber(3);
            state.pushNumber(5);
            state.pushNumber(8);
            state.call(3, 1);
            LuaObject obj = state.getLuaObject(1);
            System.out.println("nestedFunc 返回值:"+obj.getNumber());
            state.close();
        }
        
        @Test
        public void cycleTest(){
            System.out.println("--------cycle(for(){}) ---------");
            LuaState state = LuaStateFactory.newLuaState();
            state.openLibs();
            state.LdoFile(LuaDemo.luaPath + "demo.lua");
            double a,b,c;
            for(int i=0;i<cycleTimes;i++){
                a= Math.random();
                b = Math.random();
                c = Math.random();
                state.getField(LuaState.LUA_GLOBALSINDEX, "calculate");
                state.pushNumber(a);
                state.pushNumber(b);
                state.pushNumber(c);
                state.call(3, 1);
    //            state.setField(LuaState.LUA_GLOBALSINDEX, "result");
    //            LuaObject obj = state.getLuaObject("result");
                LuaObject obj = state.getLuaObject(1);
                state.pop(1);
                System.out.println(String.format(" a=%6f,b=%6f,c=%6f sum=>%6f", a,b,c,obj.getNumber()));
            }
            state.close();
        }
    //    @Test
        public void concurrentTest() throws InterruptedException {
            System.out.println("--------concurrent ---------");
            ExecutorService service = Executors.newFixedThreadPool(5);
            for(int i=0;i<cycleTimes;i++){
                service.execute(new MyMonsterThread());
            }
            Thread.sleep(5000);
            service.shutdown();
        }
    //    @Test
        public void concurrentSingleThreadTest() throws InterruptedException {
            System.out.println("--------concurrentSingleThread ---------");
            ExecutorService service = Executors.newSingleThreadExecutor();
            for(int i=0;i<cycleTimes;i++){
                service.execute(new MyMonsterThread());
            }
            service.shutdown();
        }
        @Test
        public void testFunc() throws InterruptedException{
            System.out.println("-----------testFunc-----------");
            LuaState state = LuaStateFactory.newLuaState();
            state.openLibs();
            state.LdoFile(LuaDemo.luaPath+"demo.lua");
    
            
    
            state.getField(LuaState.LUA_GLOBALSINDEX, "testFunc");
    
            state.call(0, 0);
    
            state.close();
    
    //        System.out.println(Math.toRadians(30));
    
    //        System.out.println(Math.sin(Math.toRadians(30)));
    
        }
    
    }
    
     
    
     
    
    demo.lua
    
     
    
    --对monster赋值(传入对象,返回对象)
    
    function create(monster)
    
    monster:setRace("the first demo")
    
    monster:setDefense(10)
    
    att = monster:getAttack()
    
    print("monster.attack=>"..att)
    
    monster:setAttack(10-att)
    
    monster:setLife(100)
    
    print("create monster !");
    
    return monster
    
    end
    
     
    
    --打印输出测试
    
    function hello()
    
        print("Hello World from Lua !");
    
    end
    
    --数值计算结果输出
    
    function calculate(a,b,c)
    
        return a+b+c
    
    end
    
    --多返回值测试
    
    function getValues(a,b,c)
    
    return a,b,c
    
    end
    
    --函数嵌套调用
    
    function nestedFunc(a,b,c)
    
    printFunc()
    
        return calculate(a,b,c)
    
    end
    
    function printFunc()
    
    print("提供给nestedFunc 函数调用的打印函数 !");
    
    end
    
    function testFunc()
    
    print("------LUA-----testFunc--------START-----")
    
    a=1
    
    b="123"
    
    c={4,5,6}
    
    d=hello
    
    print(type(a))--打印数据类型
    
    print(type(b))
    
    print(type(c))
    
    print(type(d))
    
    print(_VERSION)--_VERSION 打印LUA版本
    
    print( a, b,c, d)--多个返回值输出
    
    --多行数据
    
    reservedWords =[[Lua reserved words are:
    
    and, break, do, else, elseif,end, false,
    
    for, function, if, in, local, nil, not,
    
    or,repeat, return, then, true, until, while]]
    
    print(reservedWords)
    
     
    
    --多个变量赋值
    
    a1,a2,a3=1,"2_",3
    
    print(a1,a2,a3)
    
    --数据互换
    
    b1,b2=3,5
    
    print(b1,b2)
    
    b1,b2=b2,b1
    
    print(b1,b2)
    
     
    
    a,b,c,d,e = 1, 1.123, 1E9, -123, .0008
    
    print("a="..a, "b="..b, "c="..c, "d="..d, "e="..e) --字符串连接用 .. 取代"+"
    
     
    
     
    
    io.write("io.write writes to stdout but without new line.")
    
    io.write(" Use an empty print to write a single new line.")
    
    print()
    
     
    
    a={} -- {} empty table
    
    b={1,2,3}
    
    c={"a","b","c"}
    
    print(a,b,c) -- tables 不能被直接打印
    
     
    
    ---------测试object格式数据----------------
    
    user={}
    
    user.username="linfenliang"
    
    user.password="123456"
    
    user.age=26
    
    user.isMan=true
    
     
    
    if(user.age>20) then
    
    print(user.username ,"is more than 20 years old!")
    
    elseif(user.age>10) then
    
    print(user.username, "maybe a student")
    
    else
    
    print(user.username, "is just a little boy ")
    
    end
    
     
    
    if(user.username=="linfenliang") then
    
    print("yes,I am linfenliang !")
    
    else
    
    print("sorry,you got the wrong guy!")
    
    end
    
     
    
    print(user.username,user.password,user.age,user.isMan)
    
     
    
    judge(user)
    
     
    
     
    
     
    
    print "------LUA-----testFunc --------END -----" --也可不添加括号
    
    end
    
    --如果 age==26,则address为 shanghai,否则为 not in shanghai
    
    function judge(user)
    
    user.address = (user.age==26) and "I am in Shanghai" or "I am not in Shanghai"
    
    print(user.address)
    
     
    
    while(user.age~=30) do
    
    user.age=user.age+1
    
    io.write(" My age is growing ..."..user.age)
    
    end
    
     
    
    print()
    
     
    
    repeat
    
    user.age=user.age-1
    
    print(" I am beginning young "..user.age)
    
    until user.age==26
    
     
    
    -- 从1到4依次打印
    
    for a=1,4
    
    do print(a)
    
    end
    
     
    
    print()
    
    -- 从1到6,每次增长3
    
    for a=1,6,3
    
    do print(a)
    
    end
    
    print()
    
    --pairs 迭代table元素
    
    for key,value in pairs({12,8,9,7})
    
    do print(key,value)
    
    end
    
     
    
    arr = {1,2,3,"four","five",6}
    
    for k,v in pairs(arr)
    
    do print(k,v)
    
    end
    
     
    
    a=0
    
    while true do
    
    a=a+1
    
    if a==10 then
    
    break
    
    end
    
    end
    
    print("循环累加:"..a)
    
    --全局变量与局部变量测试
    
    sayHello()
    
    print(word_a,word_b)
    
    --字符串格式化测试
    
    io.write(string.format("hello,now is %s, I am %s, I am %s",os.date(),"linfenliang","a good man!
    "))
    
    --数学公式测试
    
    print(math.sqrt(81),math.pi,math.sin(0.5235987755982988))
    
    --字符串操作
    
    --string.byte, string.char, string.dump, string.find, string.format,
    
    --string.gfind, string.gsub, string.len, string.lower, string.match,
    
    --string.rep, string.reverse, string.sub, string.upper
    
    print(string.reverse("abcdefg"),string.rep("abcd",5),string.find("abcdeadvdsrerdv","dv"))
    
    --table测试
    
    t = {1}
    
    table.insert(t,2)
    
    table.insert(t,3)
    
    table.sort(t,function(v1,v2) return v1>v2 end)
    
    print("table t==>"..table.concat(t,":"))
    
    table.insert(t,"iii")
    
    --输出
    
    for k,v in ipairs(t)
    
    do print(k,v)
    
    end
    
    --Lua IO 操作
    
    -- IO 函数:
    
    -- io.close , io.flush, io.input, io.lines, io.open, io.output, io.popen,
    
    -- io.read, io.stderr, io.stdin, io.stdout, io.tmpfile, io.type, io.write,
    
    -- file:close, file:flush, file:lines ,file:read,
    
    -- file:seek, file:setvbuf, file:write
    
     
    
    print(io.open("E://demo.lua","r"))
    
     
    
    --os.clock, os.date, os.difftime, os.execute, os.exit, os.getenv,
    
    --os.remove, os.rename, os.setlocale, os.time, os.tmpname
    
    print(os.date())
    
     
    
    dofile("E://demo.lua")
    
     
    
    str_01 = "print("Hello,this function is load from String!")"
    
    loadstring(str_01)()
    
    math.randomseed(os.time())
    
    a = math.random(10,20)
    
    b = math.random(10,20)
    
    c = math.random(10,20)
    
    d = math.random(10,20)
    
    e = math.random(10,20)
    
    f = math.random(10,20)
    
    print(a,b,c,d,e,f)
    
     
    
    end
    
    word_a = "hello"
    
    --测试本地变量与全局变量
    
    function sayHello()
    
    local word_a = "nihao"
    
    word_b = "I am good"
    
    print(word_a,word_b)
    
    end
    
    问题
    
    1、在做并发测试时,发现如果多次创建关闭 LuaState,会出现异常,甚至会导致JVM崩溃,分析原因可能为加载编译器与执行器占用内存过大导致,但是我将JVM内存参数改为512MB还是会出现这个问题,还是有疑问。
    
    总结
    
    一直没有找到一个比较典型的使用案例,《Lua游戏开发实践指南》有些例子,还在研究。
    Lua 调用自定义C模块
    这是《Lua程序设计》中提到的,但是想成功执行,对于初学Lua的确没那么简单。这里涉及如何如何生成一个动态链接库so文件;Lua5.2中导出函数从LuaL_register变成了LuaL_newlib。对于具体的细节有待深入。这里的模块名是hello_lib, Lua解释器会根据名字找到对应的模块,而后执行其中的 luaopen_XXX方法。
    Lua程序设计(第2版)中文 PDF http://www.linuxidc.com/Linux/2013-03/81833.htm
    代码:
    #include <math.h>
    #include <lua5.2/lua.h>
    #include <lua5.2/lauxlib.h>
    #include <lua5.2/lualib.h>
    static int hello_sin(lua_State *L){
        double d = luaL_checknumber(L, 1);
        lua_pushnumber(L, sin(d));
        return 1;
    }
    static const struct luaL_Reg hello_lib[] = {
        {"hello_sin" , hello_sin},
        {NULL, NULL}
    };
    int luaopen_hello_lib(lua_State *L){
        luaL_newlib(L, hello_lib);
        //luaL_register(L, "hello_lib",hello_lib); // lua 5.1
        return 1;
    }
    
    在Lua中调用:
    local hello = require "hello_lib"
    print(hello.hello_sin(1))
    执行过程和结果:
    Lua 调用自定义C模块
    Lua 语言 15 分钟快速入门 http://www.linuxidc.com/Linux/2013-06/86582.htm
    Lua程序设计(第二版)阅读笔记 http://www.linuxidc.com/Linux/2013-03/81834.htm
    NetBSD 将支持用 Lua 脚本开发内核组件 http://www.linuxidc.com/Linux/2013-02/79527.htm
    CentOS 编译安装 Lua LuaSocket http://www.linuxidc.com/Linux/2011-08/41105.htm
    lua读写redis的环境部署
    我的lua环境是5.2版本,而对应的lua redis接口都是基于5.1的。所以首先先安装
    1. compact5.1 这个安装没什么好说的,搜到官方网站,下载即可。然后copy对应lua文件到lua对应的安装库路径
    我这里是/usr/local/lib/lua/5.2/
    2.  安装luasocke, 这个接口是实现了lua基本的网络请求接口。这个安装麻烦一点,对应的参考http://blog.csdn.net/shiningstarpxx/article/details/12911569
    3. 安装redis-lua-git, 把对应的src目录下的lua文件拷到对应的库路径即可。
    测试下面的代码,如果成功了就说明安装成功
    local redis = require 'redis'
    local myclient = redis.connect('127.0.0.1', 6379)
    response = myclient:ping()
    print( response )
    myclient:set("10000", "Hello World");
    value = http://blog.csdn.net/shiningstarpxx/article/details/myclient:get("10000")
    print(value)
    hello world
    
    增加nginx配置:
            location /hello {
                default_type text/html;
                content_by_lua '
                    ngx.say("<p>hello, world</p>")
    ngx.say(tostring(ngx.var.remote_addr),"<br/>")
    ngx.say(tostring(ngx.var.arg_name),"<br/>")
                ';
            }
    
    
    这样就可以使用nginx开发动态接口了。
    niginx的其他参数:
    非常多的扩展和使用方法
    https://github.com/chaoslawful/lua-nginx-module
    3,连接数据库redis
    
     local mysql = require "resty.mysql"
        local memcached = require "resty.memcached"
        local function query_mysql()
            local db = mysql:new()
            db:connect{
                        host = "127.0.0.1",
                        port = 3306,
                        database = "test",
                        user = "monty",
                        password = "mypass"
                      }
            local res, err, errno, sqlstate =
                    db:query("select * from cats order by id asc")
            db:set_keepalive(0, 100)
            ngx.say("mysql done: ", cjson.encode(res))
        end
        local function query_memcached()
            local memc = memcached:new()
            memc:connect("127.0.0.1", 11211)
            local res, err = memc:get("some_key")
            ngx.say("memcached done: ", res)
        end
    
    ngx.thread.spawn(query_mysql)      -- create thread 1
        ngx.thread.spawn(query_memcached)  -- create thread 2 
    
     几行lua代码计算http包总长度 
    --帮助理解一下lua里的字符串模式和捕获的使用
    --计算HTTP包总长度
    local i, j = pMsg:find("
    
    ")
    if(i ~= nil and pkgsize == 0) then
        --字符串模式匹配加捕获,j是HTTP头的长度
        pkgsize = j + tonumber(pMsg:match("Content%-Length: (%d+)"))
    end

    一起学Lua(第二篇-环境搭建)

    (2011-07-28 01:17:30)
    标签:

    杂谈

     

    一、LuaForWindows

    在搭建环境之前,肯定要一个Lua的解释器之类的东西,这些东西从哪里来?

    1.直接编译文件

    (1)http://www.lua.org/download.html下载新版本的Lua

    (2)解压进入etc/

    C:Documents and SettingsAdministrator>cd /d f:lua_study/lua-5.1.4/etc 
    

    (3)执行 luavs.bat

    F:lua_studylua-5.1.4etc>luavs.bat 
    

    (4)src目录下生成动态库等等文件,不过我在编译的时候出现了好多问题,就使用的下面的方法

    2.使用LuaForWindows

    Lua for Windows 为 Windows 系统下提供了 Lua 脚本语言的开发和运行环境,很多东西配套好了。

    直接像python一样安装一下,安装时把SciTe编辑器也选择上,像头文件,库什么的都直接放好了。

    推荐这种方法

    3.SciTe编辑器

    是一个体积小巧的文本编辑器,在安装LuaForWindows可以选择安装,并且把那个黑底色选择上更有感觉一点。

    4.下载地址

    http://code.google.com/p/luaforwindows/

    或者

    http://luaforge.net/frs/?group_id=377

    二、Script.Net的IDE环境

    蓝蚂蚁软件工作室的一个作品,用着感觉不错,用这个也是相当的方便,最主要的是它有vc番茄一样的提示

    下载地址:http://www.blueantstudio.net

    先下载 基础安装包,再下载安装Lua开发包

    一起学Lua(第二篇-环境搭建) - 熊哥 - 熊哥

    三、第一个Lua程序

    print("hello lua...")
    

    SciTe编辑器中:

    一起学Lua(第二篇-环境搭建) - 熊哥 - 熊哥

    四、Lua和VS2008的环境

    1.加入外部的头和库

    VS2008-工具-选项-VC++目录中,把LuaForWindows安装下的头文件和库文件加到目录,运行文件在安装LuaForWindows的时候加入了环境变量,可以不用加了。
    一起学Lua(第二篇-环境搭建) - 熊哥 - 熊哥

    2.第一个工程

    新建一个vc的命令行工程,写一个Lua脚本,用C++调用。

    脚本:environment_test.lua

    function ShowPrint() 
    
        print( "this is my cpp code call..." ) 
    
    end
    

    C++工程:Lua_c_evn

    //注释:这段代码是参考网上文章照猫画虎出来的,只是来验证环境正确。

      1: //------------------------------------------------- 
    
      2: //说明:Lua环境测试 
    
      3: //时间:2011-7-28 
    
      4: //环境:vs2008 
    
      5: //------------------------------------------------- 
    
      6: #include "stdafx.h" 
    
      7: #include <iostream> 
    
      8:  
    
      9: extern "C" {    
    
     10: #include <lua.h> 
    
     11: #include <lualib.h> 
    
     12: #include <lua.hpp> 
    
     13: } 
    
     14:  
    
     15: #pragma comment(lib,"lua5.1.lib")   
    
     16:  
    
     17: int _tmain(int argc, _TCHAR* argv[]) 
    
     18: { 
    
     19:   lua_State *L = lua_open(); // 
    
     20:   luaL_openlibs(L); //加载 .lib 文件  
    
     21:  
    
     22:   // 加载脚本文件,需要放在程序目录   
    
     23:   luaL_loadfile( L, "environment_test.lua" );   
    
     24:   lua_resume( L, 0 );   
    
     25:  
    
     26:   // 调用函数   
    
     27:   lua_getglobal( L, "ShowPrint" );   
    
     28:   if( lua_resume( L, 0 ) )   
    
     29:   { 
    
     30:     printf( "%s/n", lua_tostring( L, 1) );   
    
     31:   } 
    
     32:    
    
     33:   // 调用结束   
    
     34:   lua_close(L);   
    
     35:  
    
     36:   std::system("pause");   
    
     37:  
    
     38:   return 0; 
    
     39: } 
    
     40:  
    
     41: 
    

    直接运行,结果

    一起学Lua(第二篇-环境搭建) - 熊哥 - 熊哥

    OK,环境配置看来是正确了,之后,就开始真正的Lua之旅了。

    五、参考引用

    所有文章您都可以任意转载,修改,演绎,但请保持完整性并留个大妈般的出处,不要误导他人

    本文出处(熊哥)

    http://pppboy.blog.163.com/blog/static/30203796201162811730972/

    引用申明

    http://blog.csdn.net/kingsollyu/article/details/6613468

    http://blog.csdn.net/kun1234567/article/details/1929815

    http://baike.baidu.com/view/1207529.htm

    生产环境中 Ngx_lua 使用技巧和应用的范例

    2013-09-10 17:25:05     发表评论

       Rewrite phase.

       Access phase.

       Content phase.

    详细的步骤:

    1.init_by_lua  上下文http  ngx启动时执行
    2. set_by_lua  上下文 server, server if, location, location if
    3.rewrite_by_lua 上下文  http, server, location, location if
    4.access_by_lua 上下文 http, server, location, location if
    5.content_by_lua 上下文   location, location if
    6.header_filter_by_lua 上下文   http, server, location, location if
    7.body_filter_by_lua 上下文 http, server, location, location if
    8.log_by_lua 上下文 http, server, location, location if

    咱们再过滤post、get请求或者是触发了某个access、rewrite,如果发现恶意和违规的侵入的话,可以发邮件报警,好让我们第一时间收到邮件的信息。

    location = /smtp {
            default_type "text/plain";
            content_by_lua '
                local smtp = require("socket.smtp")
                local from = "<ruifengyunceshi@163.com>"
                local  rcpt = {"",}
                local   mesgt = {
                headers = {
                to = "", -- 收件人
                subject = "This is Mail Title"
                },
            body = "This is  Mail Content."
        }
         local  r, e = smtp.send{
            server="smtp.163.com",
            user="",
            password="",
            from = from,
            rcpt = rcpt,
            source = smtp.message(mesgt)
          }
        if not r then
            ngx.say(e)
        else
            ngx.say("send ok!")
        end
        ';
        }

    lua这东西挺怪的,他的双引号和单引号是有很大区别的,我到现在也没搞明白,啥区别,反正用双引号就对了。。。有事error.log报错的话,改成单引号试试。。

    好点的方法是  先在lua的环境中跑一边,ok后,在放到ngx_lua里面。

    Lua有丰富的接口的方案,不只是给别人提供的接口,还有他自己访问别的接口所用的模块。

    如果你的同事那边已经有个高性能的socket接口,那你就别麻烦他改成rest模式了。毕竟socket对socket速度很快的。

    location /cosocket {
            default_type "text/plain";
            content_by_lua '
            local sock = ngx.socket.tcp()
            sock:settimeout(1000)
            local ok, err = sock:connect("127.0.0.1", 12000)
            if not ok then
                ngx.say("failed to connect: ", err)
                return
            end
            local bytes, err = sock:send("flush_all")
            ngx.say(bytes,err)
            if not bytes then
                ngx.say("failed to send query: ", err)
                return
            end
           local line, err = sock:receive()
            if not line then
                ngx.say("failed to receive a line: ", err)
                return
            end
            ngx.say("result: ", line)
            ';
          }
                                                                                                                                                                                                                                                                                                                                                                                             
        }
    }

    对于给别人的mysql查询,给账号密码不合适,和一个小权限的账号密码也不合适。

    这种情况,我们要是求高性能的话,可以用lua配置cjson做成rest接口。

    location /select2 {
    content_by_lua '
    local mysql = require "resty.mysql"
    local db,err = mysql:new()
    if not db then
    ngx.say("failed to instantiate mysql: ",err)
    return
    end
    db:set_timeout(1000)
    local ok,err,errno,sqlstate = db:connect{
    host = "127.0.0.1",
    port = 3306,
    database = "niubi",
    user = "ruifengyun",
    password = "",
    max_package_size = 1024
    }
    if not ok then
    ngx.say("failed to connect: ", err, ": ", errno, " ", sqlstate)
    return
    end
    ngx.say("connected to mysql.")
    res,err,errno,sqlstate = db:query("select username,password from users where id="..ngx.var.arg_id)
    if not res then
    ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
    return
    end
    local cjson = require "cjson"
    ngx.say("result: “,cjson.encode(res))
    ';
    }

    咱们既然知道了 lua的强大之处, 可以从lua里面搞负载均衡。

    往redis里面 扔两个key   比如 web1 8.8.8.111  web2 8.8.8.222

    server {
      listen 80;
      server_name _;
      server_name_in_redirect off;
      port_in_redirect off;
      root /root/html;
      location / {
        set $upstream "";
        rewrite_by_lua '
          local routes = _G.routes
          -- setup routes cache if empty
          if routes == nil then
            routes = {}
            ngx.log(ngx.ALERT, "Route cache is empty.")
          end
          -- try cached route first      local route = routes[ngx.var.http_host]
          if route == nil then
            local redis  = require "redis"
            local client = redis.connect("localhost", 6379)
            route        = client:get(ngx.var.http_host)
          end
          if route ~= nil then
            ngx.var.upstream = route
            routes[ngx.var.http_host] = route
            _G.routes = routes
          else
            ngx.exit(ngx.HTTP_NOT_FOUND)
          end
        ';
        proxy_buffering             off;
        proxy_set_header            Host $host;
        proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect              off;
        proxy_connect_timeout       10;
        proxy_send_timeout          30;
        proxy_read_timeout          30;
        proxy_pass                  http://$upstream;
      }
    }

    用lua 对cookie的控制

    header_filter_by_lua '
            t = {}
            if ngx.var.http_cookie then
                s = ngx.var.http_cookie
                for k, v in string.gmatch(s, "(%w+)=([%w%/%.=_-]+)") do
                    t[k] = v
                end
            end               
            p = ngx.req.get_uri_args()                                                     
            if not t.uid and p.uid then
                expires = ngx.cookie_time(4523969511)
                ngx.header["Set-Cookie"] = {"uid=" .. p.uid .."; expires=" .. expires .. ";
            end
                                                         
    ';
  • 相关阅读:
    BugReport-仿微信app
    成长、责任、和公司的关系
    团队如何做决定
    课堂练习
    课堂练习
    NABCD model
    课堂练习
    日程管理测试用例
    测试
    Bug报告
  • 原文地址:https://www.cnblogs.com/timssd/p/4753595.html
Copyright © 2011-2022 走看看