Lua获取网络时间

作者:ani_di 
版权所有,转载务必保留此链接 http://blog.csdn.net/ani_di

Lua获取网络时间

网络授时服务是一些网络上的时间服务器提供的时间,一般用于本地时钟同步。 授时服务有很多种,一般我们选择RFC-868。这个协议的工作流程是:(S代表Server,C代表Client)

  1. S: 检测端口37
  2. U: 连接到端口37
  3. S: 以32位二进制数发送时间
  4. U: 接收时间
  5. U: 关闭连接
  6. S: 关闭连接

协议非常简单,用TCP连接上后,服务器直接把时间发送回来。发送的是从1900年1月1日午夜到现在的秒数。

使用luasocket

实现的方案有很多种,Lua不一定是最简单的,选择只是出于个人兴趣。直接上代码吧

-----------------------------------------------------------------------------

-- Network Time Protocal

-- Author: ani_di

-----------------------------------------------------------------------------

package.cpath = package.cpath .. ';D:\\tools\\Lua\\5.1\\clibs\\?.dll;?.dll'

local socket = require "socket.core"



server_ip = {

        -- "129.6.15.29",

        "132.163.4.101",

        "132.163.4.102",

        "132.163.4.103",

        "128.138.140.44",

        "192.43.244.18",

        "131.107.1.10",

        "66.243.43.21",

        "216.200.93.8",

        "208.184.49.9",

        "207.126.98.204",

        "207.200.81.113",

        "205.188.185.33"}



function nstol(str)

    assert(str and #str == 4)

    local t = {str:byte(1,-1)}

    local n = 0

    for k = 1, #t do

        n= n*256 + t[k]

    end

    return n

end



-- get time from a ip address, use tcp protocl

function gettime(ip)

    print('connect ', ip)

    local tcp = socket.tcp()

    tcp:settimeout(10)

    tcp:connect(ip, 37)

    success, time = pcall(nstol, tcp:receive(4))

    tcp:close()

    return success and time or nil

end



function nettime()

    for _, ip in pairs(server_ip) do

        time = gettime(ip)

        if time then 

            return time

        end

    end

end

代码原理不细说,非常简单。唯一值得一提的是socket库包含。最开始用的这句 require "socket"

在解释器中表现很好,但在用C中调用会找不到相应的module。错误提示

    no field package.preload['socket']

    no file '.\socket.lua'

    no file 'F:\Projects\Lua\nettime\lua\socket.lua'

    no file 'F:\Projects\Lua\nettime\lua\socket\init.lua'

    no file 'F:\Projects\Lua\nettime\socket.lua'

    no file 'F:\Projects\Lua\nettime\socket\init.lua'

    no file 'D:\tools\Lua\5.1\lua\socket.luac'

    no file '.\socket.dll'

    no file '.\socket51.dll'

    no file 'F:\Projects\Lua\nettime\socket.dll'

    no file 'F:\Projects\Lua\nettime\socket51.dll'

    no file 'F:\Projects\Lua\nettime\clibs\socket.dll'

    no file 'F:\Projects\Lua\nettime\clibs\socket51.dll'

    no file 'F:\Projects\Lua\nettime\loadall.dll'

    no file 'F:\Projects\Lua\nettime\clibs\loadall.dll'.

网上也有好多类似的提问,大抵是没仔细看作者的Guide。显著的有这么一句

The other two environment variables instruct the compatibility module to look for dynamic libraries and extension modules in the appropriate directories and with the appropriate filename extensions.>

LUAPATH=/?.lua;?.lua LUACPATH=/?.dll;?.dll

至于"socket.core",windows默认安装位于“\socket\core.dll”。

C宿主调用

#include <stdio.h>

#include <string.h>

#include <lua.h>

#include <lauxlib.h>

#include <lualib.h>

#include <time.h>

#include <Windows.h>



int load(lua_State* L, const char* func, unsigned int* utc) {

   lua_getglobal(L, func);

   if (lua_pcall(L, 0, 1, 0)) {

        printf("Error Msg pcall %s.\n", lua_tostring(L, -1));

        return -1;

   }



   if (!lua_isnumber(L,-1)) {

       printf("time should be a number\n" );

       return -2;

   }



   *utc = lua_tonumber(L,-1);

   lua_pop(L, -1);

   return 0;

}



void TimetToFileTime( time_t t, LPFILETIME pft )

{

    LONGLONG ll = Int32x32To64(t, 10000000) + 116444736000000000;

    pft->dwLowDateTime = (DWORD) ll;

    pft->dwHighDateTime = ll >>32;

}



int main()

{

   lua_State* L = luaL_newstate();

   unsigned int utc = 0;

   luaL_openlibs(L);

  if (luaL_loadfile(L, "nettime.lua") || lua_pcall(L, 0, 0, 0)) {

       printf("Error Msg load %s.\n", lua_tostring(L, -1));

       return -1;

   }

   do {

    if(load(L,"nettime", &utc) == 0) {

        time_t tt = utc - 2208988800L;

        SYSTEMTIME st;

        FILETIME ft;

        TimetToFileTime(tt, &ft);

        if (FileTimeToSystemTime(&ft, &st))

        {

            printf("Today is: %d-%d-%d\n", st.wYear, st.wMonth, st.wDay);

            SetSystemTime(&st);

        }

        break;

    } else {

        puts("No network!");

        Sleep(10000);

    }

   } while (1);

   lua_close(L);

   return 0;

}

你可能感兴趣的:(lua)