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;
}
(0)

相关推荐

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

    网络授时服务是一些网络上的时间服务器提供的时间,一般用于本地时钟同步. 授时服务有很多种,一般我们选择RFC-868.这个协议的工作流程是:(S代表Server,C代表Client) S: 检测端口37 U: 连接到端口37 S: 以32位二进制数发送时间 U: 接收时间 U: 关闭连接 S: 关闭连接 协议非常简单,用TCP连接上后,服务器直接把时间发送回来.发送的是从1900年1月1日午夜到现在的秒数. 使用luasocket 实现的方案有很多种,Lua不一定是最简单的,选择只是出于个人兴趣

  • android-获取网络时间、获取特定时区时间、时间同步的方法

    最近整理出android-获取网络时间.获取特定时区时间.时间同步的方法.具体如下: 方法一: SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dff.setTimeZone(TimeZone.getTimeZone("GMT+08")); String ee = dff.format(new Date()); 这个方法获取的结果是24小时制的,月份也正确. 这个方法不随手机时间

  • AJAX获取服务器当前时间及时间格式输出处理

    AJAX获取服务器当前时间 ------------------------------ WebService1.asmx---------------------------------- 复制代码 代码如下: // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释. [System.Web.Script.Services.ScriptService] public class WebService1 : System.Web.Services.WebS

  • Android编程获取网络时间实例分析

    本文实例讲述了Android编程获取网络时间的方法.分享给大家供大家参考,具体如下: 在网上看到的最常见的方式有: public static void main(String[] args) throws Exception { URL url=new URL("http://www.bjtime.cn");//取得资源对象 URLConnection uc=url.openConnection();//生成连接对象 uc.connect(); //发出连接 long ld=uc.g

  • Python 获取ftp服务器文件时间的方法

    这个问题在网上找了很长时间,也没有很好的解决方案,大多数都是用的 ftp.retrlines('LIST',处理函数) 来获得文件的时间但是格式是 所以很难做成时间戳,获取时间的目的不就是用来比较, 所以下面个大家来个可以获取时间然后转化成时间戳的方式 首先函数 直接获取ftp文件的时间 然后我的做法是,先将时间转化成列表,然后做成时间元组,再用函数转化成时间戳. L = list(ftp.sendcmd('MDTM ' + "/home/tarena/%s/%s" % (files_

  • 获取站点的各类响应时间(dns解析时间,响应时间,传输时间)

    有时候为了测试网络情况,需要返回每个阶段的耗时时间,比如DNS解析耗时,建立连接所消耗的时间,从建立连接到准备传输所使用的时间,从建立连接到传输开始所使用的时间,整个过程耗时,下载的数据量,下载速度,上传数据量,上传速度等等.下面的脚本获取以上信息: CURL的资料参见: http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html 复制代码 代码如下: ###################################### author: ww

  • Windows下通过bat获取网络连线实际名称,加强IP类设置脚本的兼容性

    其中比较难解决的问题就是获取网络连线的实际名称,大部分人使用的IP设置脚本都是将[本地连接]写死在代码中,可实际上并不是所有电脑都叫本地连接:比如有的用户电脑可能升级了网卡驱动,或者更换了网卡,导致网络连线的名称变成"本地连接2",又比如有无聊好事者(某产线的作业员电脑),将网络连线的名称各种DIY,我就见过一个修改成"操蛋的青春",瞬间无语! 好了,废话不多说,直接上菜! 对于网络连线的实际名称,可能出现的情况有: 1.网卡更换/驱动升级导致名称变更,比如本地连接

  • Java 根据网络URL获取该网页上面所有的img标签并下载图片

    说明:根据网络URL获取该网页上面所有的img标签并下载符合要求的所有图片 所需jar包:jsoup.jar import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.

  • python如何获取网络数据

    Retrieving Data over HTTP Python 内置了 sockets 可以实现与网络连接并通过 Python 提取数据的功能. socket 是可以提供双向连接的,我们可以对同一个 socket 进行读写操作.比方说,A 对 socket 写入信息,并且将其发送给 socket 连接另一端 B:那么 B 读取 socket 的内容就可以得到 A 的信息.但是这样会有一个问题,比如说, A端并没有发送任何信息,而 B 端一直在尝试读取 socket 的内容,那么 A 端和 B

  • Python利用PyQt5制作一个获取网络实时NBA数据并播报的GUI程序

    制作NBA数据爬虫 捋顺思路 我们在这里选择的是百度体育带来的数据,我们在百度当中直接搜索NBA跳转到网页,我们可以看到,百度已经为我们提供了相关的数据 我们点击进去后,可以发现这是一个非常简洁的网址 我们看一下这个地址栏,发现毫无规律https://tiyu.baidu.com/live/detail/576O5Zu955S35a2Q6IGM5Lia56%2Bu55CD6IGU6LWbI2Jhc2tldGJhbGwjMjAyMS0wNi0xMyPniLXlo6t2c%2BWspritq%2Bi

随机推荐