【问题标题】:Get the exact time for a remote server获取远程服务器的准确时间
【发布时间】:2018-10-27 11:50:31
【问题描述】:

在 C# 中,如何查询远程服务器的当前时间?

类似的功能
net time \\servername

但返回包含秒数的日期戳。

谢谢

【问题讨论】:

    标签: c# .net time


    【解决方案1】:

    您可以使用NetRemoteTOD 函数。

    来自http://bytes.com/groups/net-c/246234-netremotetod-usage的例子:

    // The pointer.
    IntPtr pintBuffer = IntPtr.Zero;
    
    // Get the time of day.
    int pintError = NetRemoteTOD(@"\\sony_laptop", ref pintBuffer);
    
    // Get the structure.
    TIME_OF_DAY_INFO pobjInfo = (TIME_OF_DAY_INFO)
    Marshal.PtrToStructure(pintBuffer, typeof(TIME_OF_DAY_INFO));
    
    // Free the buffer.
    NetApiBufferFree(pintBuffer);
    

    【讨论】:

    • 像魅力一样工作。它不需要远程服务器来运行Windows 时间服务(@Reed Copsey 回答)或端口 13 打开(@Zanoni 回答)或访问文件系统(@bluish 回答)。此方法适用于 Windows 2000 或更高版本 - 完美..
    【解决方案2】:

    您可以尝试在端口 13 上获取白天:

    System.Net.Sockets.TcpClient t = new System.Net.Sockets.TcpClient ("yourmachineHOST", 13);
    System.IO.StreamReader rd = new System.IO.StreamReader (t.GetStream ()); 
    Console.WriteLine (rd.ReadToEnd ());
    rd.Close();
    t.Close();
    

    【讨论】:

    • 一个不错的简单解决方案,如果远程服务器打开了端口 13...您可以使用 telnet yourmachineHOST 13 非常简单地测试端口是否打开并查看是否收到响应
    【解决方案3】:

    下面是更完整的实现。

    用法:DateTime? now = RemoteTOD.GetNow(@"\\ServerName");

    using System;
    using System.ComponentModel;
    using System.Runtime.InteropServices;
    
    //https://docs.microsoft.com/en-us/windows/desktop/api/lmremutl/nf-lmremutl-netremotetod
    public static class RemoteTOD {
    
        // Important: CharSet must be Unicode otherwise error 2184 is returned
        [DllImport("netapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
        private static extern int NetRemoteTOD(String UncServerName, ref IntPtr BufferPtr);
    
        [DllImport("netapi32.dll")]
        private static extern void NetApiBufferFree(IntPtr bufptr);
    
        public static DateTime? GetNow(String serverName, bool throwException = false) {
            IntPtr ptrBuffer = IntPtr.Zero;
            int result = NetRemoteTOD(serverName, ref ptrBuffer);
            if (result != 0) {
                if (throwException)
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                return null;
            }
    
            TIME_OF_DAY_INFO tod = (TIME_OF_DAY_INFO) Marshal.PtrToStructure(ptrBuffer, typeof(TIME_OF_DAY_INFO));
            NetApiBufferFree(ptrBuffer); // must be freed using NetApiBufferFree according to the documentation
    
            //DateTime d0 = new DateTime(1970,1,1);
            //d0 = d0.AddSeconds(tod.elapsedt);
            DateTime nowUtc = new DateTime(tod.year, tod.month, tod.day, tod.hour, tod.minute, tod.second, 10 * tod.hunds);
            DateTime now = nowUtc.ToLocalTime();
            return now;
        }
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct TIME_OF_DAY_INFO {
    
        ///<summary>The number of seconds since 00:00:00, January 1, 1970, GMT.</summary>
        public int elapsedt;
    
        ///<summary>The number of milliseconds from an arbitrary starting point (system reset). Typically, this member is read twice,
        ///once when the process begins and again at the end. To determine the elapsed time between the process's start and finish,
        ///you can subtract the first value from the second.</summary>
        public int msecs;
    
        ///<summary>The current hour. Valid values are 0 through 23.</summary>
        public int hour;
    
        ///<summary>The current minute. Valid values are 0 through 59.</summary>
        public int minute;
    
        ///<summary>The current second. Valid values are 0 through 59.</summary>
        public int second;
    
        ///<summary>The current hundredth second (0.01 second). Valid values are 0 through 99.</summary>
        public int hunds;
    
        ///<summary>The time zone of the server. This value is calculated, in minutes, from Greenwich Mean Time (GMT). For time zones
        ///west of Greenwich, the value is positive; for time zones east of Greenwich, the value is negative. A value of –1 indicates
        ///that the time zone is undefined.</summary>
        public int timezone;
    
        ///<summary>The time interval for each tick of the clock. Each integral integer represents one ten-thousandth second (0.0001 second).</summary>
        public int tinterval;
    
        ///<summary>The day of the month. Valid values are 1 through 31.</summary>
        public int day;
    
        ///<summary>The month of the year. Valid values are 1 through 12.</summary>
        public int month;
    
        ///<summary>The year.</summary>
        public int year;
    
        ///<summary>The day of the week. Valid values are 0 through 6, where 0 is Sunday, 1 is Monday, and so on.</summary>
        public int weekday;
    }
    

    【讨论】:

      【解决方案4】:

      Windows 时间服务实现了 NTP。这是C# implementation of an NTP client。使用它的 Windows GUI 可以在Simple Network Time Protocol Client 找到。这是 Valer Bocan 的作品。

      【讨论】:

      • 如果无法查询实际远程服务器的时间;您至少可以查询相同的域控制器/ NTP 服务器并获得非常相似的时间。使用引用的 NTP 客户端就像 var client = new InternetTime.SNTPClient("pkh-srv-dc03");客户端.连接(假); Console.WriteLine(client.DestinationTimestamp);
      【解决方案5】:

      使用 Reed Copsey (& David Laing) 答案中的 C# NTP client,您可以使用以下方式从域控制器/NTP 服务器获取“现在”时间戳(以毫秒为单位):

      InternetTime.SNTPClient sntp = new InternetTime.SNTPClient("ntp1.ja.net");
      sntp.Connect(false); // true to update local client clock
      DateTime dt = sntp.DestinationTimestamp.AddMilliseconds(sntp.LocalClockOffset);
      string timeStampNow = dt.ToString("dd/MM/yyyy HH:mm:ss.fff");
      

      【讨论】:

      • 你可以把这段代码发到@Reed Copsey's answer,这样会得到增强,方便以后的读者理解。 ;)
      【解决方案6】:

      【讨论】:

      • 对不起,这个答案没用,它指向与@Reed Copsey's answer 相同的项目。我会将您的链接粘贴到那个答案上,我认为这个答案应该被关闭。谢谢!
      【解决方案7】:

      如果您可以通过 UNC 路径访问远程系统的文件系统(例如 \\remotehost\foo\bar;例如使用 Windows 资源管理器),您可以检索远程日期时间,即使它是不是 Windows 系统,有以下解决方法。创建一个虚拟文件,读取它的写入时间并将其丢弃。它也适用于本地主机。

      public DateTime filesystemDateTime(string path)
      {
          //create temp file
          string tempFilePath = Path.Combine(path, "lampo.tmp");
          using (File.Create(tempFilePath)) { }
          //read creation time and use it as current source filesystem datetime
          DateTime dt = new FileInfo(tempFilePath).LastWriteTime;
          //delete temp file
          File.Delete(tempFilePath);
      
          return dt;
      }
      

      【讨论】:

        【解决方案8】:
        class RemoteSystemTime 
            {
                static void Main(string[] args)
                {
                    try
                    {
                        string machineName = "vista-pc";
        
                        System.Diagnostics.Process proc = new System.Diagnostics.Process();
                        proc.StartInfo.UseShellExecute = false;
                        proc.StartInfo.RedirectStandardOutput = true;
                        proc.StartInfo.FileName = "net";
                        proc.StartInfo.Arguments = @"time \\" + machineName;
                        proc.Start();
                        proc.WaitForExit();
        
                        List<string> results = new List<string>();
                        while (!proc.StandardOutput.EndOfStream)
                        {
                            string currentline = proc.StandardOutput.ReadLine();
                            if (!string.IsNullOrEmpty(currentline))
                            {
                                results.Add(currentline);
                            }
                        }
        
                        string currentTime = string.Empty;
                        if (results.Count > 0 && results[0].ToLower().StartsWith(@"current time at \\" +                                               machineName.ToLower() + " is "))
                        {
                            currentTime = results[0].Substring((@"current time at \\" + machineName.ToLower() + " is                             ").Length);
        
                            Console.WriteLine(DateTime.Parse(currentTime));
                            Console.ReadLine();
                        }
        
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                        Console.ReadLine();
                    }
                }
        

        【讨论】:

        • 请注意,如果本地计算机上的语言不是英语,则“当前时间”是不正确的。
        • 顺便说一句:NET TIME 命令 使用 NetRemoteTOD 函数(来自@Patrick McDonald 的回答):blogs.msdn.com/b/w32time/archive/2009/08/07/…
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-05-09
        • 1970-01-01
        • 1970-01-01
        • 2014-03-20
        • 2018-07-12
        • 1970-01-01
        • 2017-10-23
        相关资源
        最近更新 更多