zoukankan      html  css  js  c++  java
  • 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:ProjectsLua
    ettimeluasocket.lua'
        no file 'F:ProjectsLua
    ettimeluasocketinit.lua'
        no file 'F:ProjectsLua
    ettimesocket.lua'
        no file 'F:ProjectsLua
    ettimesocketinit.lua'
        no file 'D:	oolsLua5.1luasocket.luac'
        no file '.socket.dll'
        no file '.socket51.dll'
        no file 'F:ProjectsLua
    ettimesocket.dll'
        no file 'F:ProjectsLua
    ettimesocket51.dll'
        no file 'F:ProjectsLua
    ettimeclibssocket.dll'
        no file 'F:ProjectsLua
    ettimeclibssocket51.dll'
        no file 'F:ProjectsLua
    ettimeloadall.dll'
        no file 'F:ProjectsLua
    ettimeclibsloadall.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默认安装位于“socketcore.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.
    ", lua_tostring(L, -1));
            return -1;
       }
    
       if (!lua_isnumber(L,-1)) {
           printf("time should be a number
    " );
           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.
    ", 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
    ", st.wYear, st.wMonth, st.wDay);
                SetSystemTime(&st);
            }
            break;
        } else {
            puts("No network!");
            Sleep(10000);
        }
       } while (1);
       lua_close(L);
       return 0;
    }
  • 相关阅读:
    可执行程序的装载
    stdafx.h的作用
    AI调色板
    3ds max输出图片
    3ds max移除几何体的线段
    3ds max删除了对象后,还是将原来所有对象输出的原因
    vs win32 & MFC 指针默认位置
    3ds max 分离对象
    PDF
    endnote设置文献第二行悬挂缩进办法
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3190279.html
Copyright © 2011-2022 走看看