当前位置: 移动技术网 > IT编程>脚本编程>Lua > Lua获取网络时间(获取时间同步服务器的时间)

Lua获取网络时间(获取时间同步服务器的时间)

2017年12月08日  | 移动技术网IT编程  | 我要评论

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

s: 检测端口37
u: 连接到端口37
s: 以32位二进制数发送时间
u: 接收时间
u: 关闭连接
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;
}

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网