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

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

相关推荐
对象存储与RustFS14 小时前
网盘限速逼你开会员?用 RustFS 自己搭一个不限速的“私人网盘
服务器·后端·docker
众壹新能源科技16 小时前
逆变器自带无功不够用,加装5MVar SVG后功率因数从0.85回到0.99
运维·人工智能·自动化
..Dauntless..16 小时前
【Linux】一切皆文件和缓冲区
linux·运维·服务器
裕晟资质规划16 小时前
三类资质变更报告时限差在哪?军工 15 日、集成印制 10 日
大数据·服务器·网络
QMCY_jason16 小时前
x86 ubuntu2204 无gui 安装 openeuler 2203 aarch64版本
linux·运维·服务器
2501_9226395816 小时前
率能半导体 SS6285L直流双向马达驱动芯片:18V/5A,覆盖电子锁、按摩仪、电动玩具、机器人四大应用场景
单片机·嵌入式硬件·硬件工程
重生之小比特17 小时前
【Linux系统】12 进程程序替换 自定义Shell 命令行解释器
linux·运维·服务器
轻舟技术A17 小时前
Provider 不属于 Agent 核心:rpi 的分层理由与收益
服务器·网络
考拉讲支付17 小时前
母婴亲子服务平台分账架构设计:多场景多方分账与合规清结算实践
大数据·运维·人工智能·微信小程序·架构·微信公众平台
连山齐名17 小时前
ai应用开发的学习笔记
服务器·笔记·学习