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

网络授时服务是一些网络上的时间服务器提供的时间,一般用于本地时钟同步。 授时服务有很多种,一般我们选择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;

}

以上是 Lua获取网络时间(获取时间同步服务器的时间) 的全部内容, 来源链接: utcz.com/z/315293.html

回到顶部