【以麒麟服务器时间为准,定时请求时间同步】

cpp 复制代码
    //定时时间同步
    QTimer              *m_pTimeSync    = nullptr;
#ifdef Q_OS_WIN
    #include <windows.h>
#else
    #include <sys/time.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
#endif

其余头文件未写出(网络通信等)
     m_pTimeSync = new QTimer();
    connect(m_pTimeSync, &QTimer::timeout, this, &SysMonitor::syncTimeFromServer);
    m_pTimeSync->start(nnTimeMinute * 60 * 1000);


//具体实现
void syncTimeFromServer()
{
    QTcpSocket socket;
    socket.connectToHost(m_strTimeServerIP, 37);
    if (!socket.waitForConnected(3000))
    {
       LogHelper::error("[syncTimeFromServer] tcpNetError: " + socket.errorString());
       return ;
    }

    // 第二步:读取时间数据(RFC 868 协议,4字节大端整数)
    if (!socket.waitForReadyRead(3000))
    {
        LogHelper::error("[syncTimeFromServer] tcpReadTimeOut!");
        return ;
    }

    QByteArray data = socket.readAll();
    if (data.size() != 4)
    {
        LogHelper::error("[syncTimeFromServer] tcpReadDateError!");
        return ;
    }

    // 第三步:解析时间戳(大端序)
    quint32 networkTime = 0;
    networkTime |= (unsigned char)data[0] << 24;
    networkTime |= (unsigned char)data[1] << 16;
    networkTime |= (unsigned char)data[2] << 8;
    networkTime |= (unsigned char)data[3];

    // RFC 868 时间戳(1900-01-01 起)转 Unix 时间戳(1970-01-01 起)
    if (networkTime < 2208988800UL)
    {
        LogHelper::error("[syncTimeFromServer] Invalid network time!");
        return;
    }
    qint64 unixTime = static_cast<qint64>(networkTime) - 2208988800LL;
    LogHelper::debug("[syncTimeFromServer] getTime: " + QString::number(unixTime));

    // 第四步:设置系统时间(需要 root 权限)
#ifdef Q_OS_WIN
    // ---------- Windows 平台 ----------
    // 1. 启用 SE_SYSTEMTIME_NAME 特权
    HANDLE hToken = nullptr;
    if (!OpenProcessToken(GetCurrentProcess(),
                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                          &hToken))
    {
        LogHelper::error("[syncTimeFromServer] OpenProcessToken error: "
                         + QString::number(GetLastError()));
        return;
    }

    LUID luid;
    if (!LookupPrivilegeValue(nullptr, SE_SYSTEMTIME_NAME, &luid))
    {
        LogHelper::error("[syncTimeFromServer] LookupPrivilegeValue error: "
                         + QString::number(GetLastError()));
        CloseHandle(hToken);
        return;
    }

    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), nullptr, nullptr))
    {
        LogHelper::error("[syncTimeFromServer] AdjustTokenPrivileges error: "
                         + QString::number(GetLastError()));
        CloseHandle(hToken);
        return;
    }
    // 注意:AdjustTokenPrivileges 返回 TRUE 也可能是失败
    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        LogHelper::error("[syncTimeFromServer] 当前进程没有 SE_SYSTEMTIME_NAME 特权,请以管理员身份运行");
        CloseHandle(hToken);
        return;
    }
    CloseHandle(hToken);

    // 2. Unix 时间戳 -> SYSTEMTIME (UTC)
    //    unixTime 是秒数,先转成 FILETIME 更方便
    //    FILETIME 起点:1601-01-01 00:00:00 UTC
    //    Unix 起点:1970-01-01 00:00:00 UTC
    //    两者相差 11644473600 秒
    ULARGE_INTEGER ull;
    ull.QuadPart = (static_cast<ULONGLONG>(unixTime) + 11644473600ULL) * 10000000ULL; // 100ns 单位

    FILETIME ft;
    ft.dwLowDateTime  = ull.LowPart;
    ft.dwHighDateTime = ull.HighPart;

    SYSTEMTIME st;
    if (!FileTimeToSystemTime(&ft, &st))
    {
        LogHelper::error("[syncTimeFromServer] FileTimeToSystemTime error: "
                         + QString::number(GetLastError()));
        return;
    }

    // 3. 设置 UTC 系统时间(与 Linux settimeofday 语义一致)
    if (SetSystemTime(&st))
    {
        LogHelper::debug("[syncTimeFromServer] SetSystemTime successful!");
    }
    else
    {
        LogHelper::error("[syncTimeFromServer] SetSystemTime error: "
                         + QString::number(GetLastError()));
    }
#else
    struct timeval tv;
    tv.tv_sec = static_cast<time_t>(unixTime);
    tv.tv_usec = 0;
    if (settimeofday(&tv, nullptr) == 0)
    {
        LogHelper::debug("[syncTimeFromServer] settimeofday sccessful!");
    }
    else
    {
        LogHelper::error("[syncTimeFromServer] settimeofday error!" );
        perror("settimeofday");
    }
#endif
}
cpp 复制代码
A.确保服务器的时间服务开启
1.安装
    sudo rpm -ivh xinetd-2.3.15-35.ky10.x86_64.rpm
2.编辑文件
    sudo vim /etc/xinetd.d/time
3.
  service time
{
    disable     = no
    type        = INTERNAL
    id          = time-stream
    socket_type = stream
    protocol    = tcp
    user        = root
    wait        = no
}
4.执行重启
   sudo systemctl restart xinetd
5.检查端口:
   time 服务使用 TCP 37 端口,可以用 netstat -tlnp | grep 37 或 ss -tlnp | grep 37 检查是否处于监听状态
6.开启防火墙需要放行37端口
sudo firewall-cmd --permanent --add-port=37/tcp
sudo firewall-cmd --reload
7.建议确认它已设为开机自启:
sudo systemctl enable xinetd
sudo systemctl status xinetd   # 确认状态是 active (running)

安装包:

https://download.csdn.net/download/chubu3218/93517721

相关推荐
海盗12341 小时前
AI 新闻日报 2026-09-28:正确性审查自动化、7×24 个人智能体、具身部署态
运维·人工智能·机器人·自动化·人工智能aigc
元岳数字人小元1 小时前
数字人源码系统:模块化开发赋能智能场景灵活迭代升级
运维·人工智能·开源·人机交互·交互
Tairitsu_H1 小时前
[Linux系统] 基础IO核心 | 系统接口 | 文件描述符 | 重定向
linux·服务器·文件操作
沐欣工作室_lvyiyi2 小时前
基于STM32单片机汽车充电桩控制模块设计(论文+源码)
stm32·单片机·汽车·毕业设计
嵌入式-老费2 小时前
esp32开发与应用(用Python+PySide6解决上位机开发)
linux·单片机·嵌入式硬件
平凡灵感码头2 小时前
HNB 加热不燃烧:从加热仓到 MCU,拆一套小型精准热管理系统
单片机·嵌入式硬件
事已至此先睡覺吧2 小时前
(三)Linux 基础指令(二):基础常用的一些指令
linux·运维·服务器
逐梦之程2 小时前
嵌入式固件升级IAP及调试软件
stm32·单片机
不会写DN2 小时前
Go日志库工程选型与逃逸分析评测报告
java·服务器·golang