跨系统时间戳同步问题解决总结

一、问题背景

多个传感器分布在不同的主机上,且主机之间用局域网连接,但都与外网隔绝;在此情况下需要统一主机时间,否则传感器数据难以同步。

两台电脑需要时间同步:

  • 电脑A :Windows系统(10.*..102),作为时间戳发送方
  • 电脑B :Linux系统(10.*..101),作为时间戳接收方

内网环境,无法访问外网NTP服务器。


二、思考与排查过程

1. 最初尝试:NTP服务器方案

尝试将Linux配置为NTP服务器,Windows作为客户端同步。

Linux端配置:

bash 复制代码
# 安装ntp
sudo apt install ntp -y

# 配置/etc/ntp.conf
sudo tee /etc/ntp.conf <<EOF
server 127.127.1.0
fudge 127.127.1.0 stratum 10
restrict 10.111.34.0 mask 255.255.255.0 nomodify notrap
restrict 127.0.0.1
restrict ::1
restrict default ignore
driftfile /var/lib/ntp/drift
EOF

sudo systemctl restart ntp

Windows端同步:

cmd 复制代码
w32tm /config /manualpeerlist:"10.111.34.101" /syncfromflags:manual /reliable:yes /update
net stop w32time && net start w32time
w32tm /resync

2. 问题发现:网络通但同步失败

通过抓包发现网络是通的,但Windows不认Linux的NTP响应:

bash 复制代码
# Linux上抓包
sudo tcpdump -i any udp port 123 -vv

抓包结果显示Linux有回复,但包含[bad udp cksum],Windows可能因此丢弃数据包。

3. 方案转向:自定义Python脚本

既然标准NTP协议不行,改用简单的UDP自定义协议,Windows发送时间戳,Linux接收并设置时间。


三、最终解决方案

步骤1:Windows发送端脚本

创建 time_sender.py

python 复制代码
import socket
import struct
import time

def send_timestamp():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    linux_ip = "10.111.34.101"
    port = 12345
    
    while True:
        timestamp = time.time()
        data = struct.pack('d', timestamp)
        sock.sendto(data, (linux_ip, port))
        print(f"发送: {timestamp:.3f} -> {time.ctime(timestamp)}")
        time.sleep(1)

if __name__ == "__main__":
    send_timestamp()

步骤2:Linux接收并设置时间脚本

创建 time_receiver.py

python 复制代码
import socket
import struct
import time
import os

def set_system_time(timestamp):
    date_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(timestamp))
    os.system(f"sudo date -s '{date_str}'")
    os.system("sudo hwclock --systohc 2>/dev/null")  # 同步硬件时钟
    print(f"时间已设置为: {date_str}")

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("0.0.0.0", 12345))
print("等待接收时间戳...")

last_time = 0
while True:
    data, addr = sock.recvfrom(1024)
    win_time = struct.unpack('d', data)[0]
    
    print(f"\n收到来自 {addr[0]}:{win_time:.3f}")
    
    # 只在时间变化较大时设置(避免频繁设置)
    if abs(win_time - last_time) > 0.5:
        set_system_time(win_time)
        last_time = win_time

步骤3:Linux监控脚本(查看时间差)

创建 time_check.py

python 复制代码
import socket
import struct
import time

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("0.0.0.0", 12345))
print("监控时间差...")

while True:
    data, addr = sock.recvfrom(1024)
    win_time = struct.unpack('d', data)[0]
    local_time = time.time()
    diff = win_time - local_time
    print(f"Windows: {win_time:.3f} | Linux: {local_time:.3f} | 差值: {diff:+.3f}秒")

四、运行流程

1. 在Linux上启动接收端(需要root权限)

bash 复制代码
sudo python3 time_receiver.py

2. 在Linux上另开终端启动监控(可选)

bash 复制代码
python3 time_check.py

3. 在Windows上启动发送端

cmd 复制代码
python time_sender.py

五、关键命令总结

用途 命令
Linux设置时间 sudo date -s "2026-03-12 20:30:00"
Linux查看时间 date
Windows设置时间 date 2026-03-12time 20:30:00
抓包诊断 sudo tcpdump -i any udp port 123 -vv
NTP服务状态 ntpq -p
Windows时间服务 w32tm /query /status

六、方案优势

  1. 简单可靠:绕过复杂的NTP协议,直接用UDP传输时间戳
  2. 完全可控:可以监控时间差,确保同步精度
  3. 内网可用:不依赖外网,适合封闭环境
  4. 跨平台:Python脚本可在Windows/Linux运行

这个方案最终成功解决了内网环境下Windows和Linux系统间的时间同步问题,实现了时间戳的对齐需求。

相关推荐
wsoz2 小时前
文件IO讲解
linux·嵌入式
mounter6252 小时前
基于MLX设备的Devlink 工具全指南与核心架构演进
linux·运维·服务器·网络·架构·kernel
wefg13 小时前
【计算机网络】网络基础 - 1(网络协议/TCP/IP协议栈/局域网内外数据传输/数据封装、解包、分用)
linux·服务器·网络
xuanwojiuxin3 小时前
[linux] what‘s the kdump?
linux·运维·服务器
无盐海3 小时前
Linux vi 命令 Docker命令
linux·docker
如若1234 小时前
WSL2安装Ubuntu完整教程:自定义安装目录到D盘(--location一键搞定)
linux·运维·服务器·pytorch·python·ubuntu·计算机视觉
papaofdoudou6 小时前
QEMU和KVMTOOL在GPA(IOVA)和HVA映射方面的异同
linux·运维·服务器
艾莉丝努力练剑6 小时前
文件描述符fd:跨进程共享机制
java·linux·运维·服务器·开发语言·c++