Luaネットワーク取得時間(取得時間同期サーバの時間)

5175 ワード

ネットワーク時間指定サービスは、ローカルクロック同期に一般的に使用されるネットワーク上の時間サーバが提供する時間である.時間割サービスはいろいろありますが、一般的には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
ettime\lua\socket.lua' no file 'F:\Projects\Lua
ettime\lua\socket\init.lua' no file 'F:\Projects\Lua
ettime\socket.lua' no file 'F:\Projects\Lua
ettime\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
ettime\socket.dll' no file 'F:\Projects\Lua
ettime\socket51.dll' no file 'F:\Projects\Lua
ettime\clibs\socket.dll' no file 'F:\Projects\Lua
ettime\clibs\socket51.dll' no file 'F:\Projects\Lua
ettime\loadall.dll' no file 'F:\Projects\Lua
ettime\clibs\loadall.dll'.

ネット上にも似たような質問がたくさんありますが、たいてい作者のガイドをよく見ていません.顕著にこんな言葉がある
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 
#include 
#include 
#include 
#include 
#include 
#include 

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; }