Получить точное время для удаленного сервера

В С#, как мне запросить удаленный сервер для его текущего времени?

Функционал аналогичен

net time \\servername

но возвращает метку даты, которая включает секунды.

Спасибо


person David Laing    schedule 17.06.2009    source источник


Ответы (8)


Служба времени Windows реализует NTP. Вот C# реализация NTP клиент. Графический пользовательский интерфейс Windows, использующий его, можно найти по адресу Simple Network Time Protocol Client. Это Валери Бокан.

person Reed Copsey    schedule 17.06.2009
comment
Если вы не можете запросить фактическое время удаленного сервера; вы можете, по крайней мере, запросить один и тот же контроллер домена/сервер NTP и получить примерно такое же время. Использование упомянутого NTP-клиента так же просто, как var client = new InternetTime.SNTPClient(pkh-srv-dc03); клиент.Подключение(ложь); Console.WriteLine(client.DestinationTimestamp); - person David Laing; 18.06.2009

Вы можете использовать функцию 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);
person Patrick McDonald    schedule 17.06.2009
comment
Работает как шарм. И ему не нужен удаленный сервер, чтобы иметь работу службы времени (ответ Рида Копси) или открытый порт 13 (ответ Занони) или доступ к файловая система (@голубоватый ответ). Этот подход работает с Windows 2000 или выше — идеально. - person bairog; 26.05.2014

Вы можете попробовать получить дневное время на порту 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();
person Zanoni    schedule 17.06.2009
comment
Хорошее простое решение, если на удаленном сервере открыт порт 13... Вы можете просто проверить, открыт ли порт, используя telnet yourmachineHOST 13 и посмотреть, получите ли вы ответ - person David Laing; 18.06.2009

Ниже приведена более полная реализация.

Использование: 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;
}
person Loathing    schedule 27.10.2018

Использование клиента C# NTP в ответе Рида Копси (и Дэвида Лэнга) вы можете получить отметку времени «сейчас» (в мс) с контроллера домена/сервера 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");
person Ken    schedule 11.11.2011
comment
Вы можете опубликовать этот код в @Reed Copsey answer, чтобы он был улучшен и будущим читателям было легко его понять. . ;) - person bluish; 25.07.2012

Простой клиент протокола сетевого времени

person Nime Cloud    schedule 10.10.2011
comment
Извините, но этот ответ бесполезен, он указывает на тот же проект, что и @Reed Copsey answer. Я вставлю вашу ссылку на этот ответ, и я думаю, что этот ответ должен быть закрыт. Спасибо! - person bluish; 25.07.2012

Если у вас есть доступ к файловой системе удаленной системы с путем UNC (например, \\remotehost\foo\bar; например, с помощью проводника Windows), вы можете получить удаленную дату и время, даже если это не система Windows< /strong> со следующим обходным путем. Создайте фиктивный файл, прочитайте время записи и выбросьте его. Это работает также для локального хоста.

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;
}
person bluish    schedule 25.07.2012

person    schedule
comment
Обратите внимание, что текущее время неверно, если язык на вашем локальном компьютере не английский. - person bairog; 26.05.2014
comment
Кстати: команда NET TIME использует функцию NetRemoteTOD (из ответа @Patrick McDonald): blogs.msdn.com/b/w32time/archive/2009/08/07/ - person bairog; 26.05.2014