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

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

相关推荐
Decay__8 小时前
12_MySQL InnoDB 内存与锁调优 —— Buffer Pool、redo log、隔离级别与锁等待
运维·数据库·sql·mysql·架构
java_logo10 小时前
Docker 部署 Dify:轻松搭建 LLM 应用开发平台
运维·docker·容器
方便面不加香菜11 小时前
Docker Container -- 综合实战案例详解
运维·docker·容器
海洋之恒12 小时前
GitHub Actions 自动化:5 个真实运维提效案例
运维·自动化·github
迪康coolmu14 小时前
出差终端数据安全落地实战:基于迪康端点安全一体化管理系统的四道防线实践
运维·服务器·经验分享·笔记·其他·安全·php
Zwawa15 小时前
屏幕不止一种:OLED、LCD1602字符屏、TFT/IPS图形屏和串口屏怎么用,这与TTY和PTY又有什么关系
c语言·单片机·嵌入式
qq_3718021116 小时前
Ubuntu Linux中安装WorkBuddy
linux·运维·服务器·ubuntu
逃逸线LOF17 小时前
服务网关Gateway
java·运维·gateway
坤坤子吖18 小时前
Linux网络编程:TCP服务器的多进程与多线程实现
linux·服务器·开发语言·网络·c++·笔记·学习