您的位置:首页 > 编程语言 > C#

c# Internet时间服务器同步

2009-02-02 17:48 232 查看
需要用到的名空间

using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;


建立一个结构

public struct SystemTime
{
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;

/// <summary>
/// 从System.DateTime转换。
/// </summary>
/// <param name="time">System.DateTime类型的时间。</param>
public void FromDateTime(DateTime time)
{
wYear = (ushort)time.Year;
wMonth = (ushort)time.Month;
wDayOfWeek = (ushort)time.DayOfWeek;
wDay = (ushort)time.Day;
wHour = (ushort)time.Hour;
wMinute = (ushort)time.Minute;
wSecond = (ushort)time.Second;
wMilliseconds = (ushort)time.Millisecond;
}
/// <summary>
/// 转换为System.DateTime类型。
/// </summary>
/// <returns></returns>
public DateTime ToDateTime()
{
return new DateTime(wYear, wMonth, wDay, wHour, wMinute, wSecond, wMilliseconds);
}
/// <summary>
/// 静态方法。转换为System.DateTime类型。
/// </summary>
/// <param name="time">SYSTEMTIME类型的时间。</param>
/// <returns></returns>
public static DateTime ToDateTime(SystemTime time)
{
return time.ToDateTime();
}
}


要用到Windows的API函数来设置系统时间

public class Win32API
{
[DllImport("Kernel32.dll")]
public static extern bool SetLocalTime(ref SystemTime Time);
[DllImport("Kernel32.dll")]
public static extern void GetLocalTime(ref SystemTime Time);
}


用Socket获取Internet时间服务器上的时间

public void SetInternetTime()
{
// 记录开始的时间
DateTime startDT = DateTime.Now;

//建立IPAddress对象与端口,创建IPEndPoint节点:
int port = 13;
string[] whost = { "5time.nist.gov", "time-nw.nist.gov", "time-a.nist.gov", "time-b.nist.gov", "tick.mit.edu", "time.windows.com", "clock.sgi.com" };

IPHostEntry iphostinfo;
IPAddress ip;
IPEndPoint ipe;
Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建Socket

c.ReceiveTimeout = 10 * 1000;//设置超时时间

string sEX = "";// 接受错误信息

// 遍历时间服务器列表
foreach (string strHost in whost)
{
try
{
iphostinfo = Dns.GetHostEntry(strHost);
ip = iphostinfo.AddressList[0];
ipe = new IPEndPoint(ip, port);

c.Connect(ipe);//连接到服务器
if (c.Connected) break;// 如果连接到服务器就跳出
}
catch (Exception ex)
{
sEX = ex.Message;
}
}

if (!c.Connected)
{
MessageBox.Show("时间服务器连接失败!/r错误信息:" + sEX, "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}

//SOCKET同步接受数据
byte[] RecvBuffer = new byte[1024];
int nBytes, nTotalBytes = 0;
StringBuilder sb = new StringBuilder();
System.Text.Encoding myE = Encoding.UTF8;

while ((nBytes = c.Receive(RecvBuffer, 0, 1024, SocketFlags.None)) > 0)
{
nTotalBytes += nBytes;
sb.Append(myE.GetString(RecvBuffer, 0, nBytes));
}

//关闭连接
c.Close();

string[] o = sb.ToString().Split(' '); // 打断字符串

textBox1.Text = sb.ToString();

TimeSpan k = new TimeSpan();
k = (TimeSpan)(DateTime.Now - startDT);// 得到开始到现在所消耗的时间

DateTime SetDT = Convert.ToDateTime(o[1] + " " + o[2]).Subtract(-k);// 减去中途消耗的时间

//处置北京时间 +8时
SetDT = SetDT.AddHours(8);

//转换System.DateTime到SystemTime
SystemTime st = new SystemTime();
st.FromDateTime(SetDT);

//调用Win32 API设置系统时间
Win32API.SetLocalTime(ref st);

MessageBox.Show("时间已同步", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}


这个东西是收集网上的一些做法再修改了一下

用vs2008+windows xp sp2测试通过

但是始终会有±1秒的误差,但大部分误差在1秒以下,尚可接受

使用的名空间包括vs自己添加的,windows Form中用到的那部分

如果换了环境,可作相应修改
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: