NTP对时-客户端程序

#include <QObject>
class QUdpSocket;#if 0   // NTP协议帧(未使用)
typedef struct
{char  LI_VN_Mode;char  Stratum;char  Poll;char  Precision;int  RootDelay;int  RootDispersion;int  ReferenceIdentifier;quint64  ReferenceTimeStamp;    // 系统时钟最后一次被设定或更新的时间quint64   OriginateTimeStamp;    // NTP请求报文离开发送端时发送端的本地时间quint64   ReceiveTimeStamp;      // NTP请求报文到达Server端时接收端的本地时间。quint64   TransmitTimeStamp;     // 发送时间戳,客户端发送时填写,server接收到后会将TransmitTimeStamp值写入OriginateTimeStamp,然后NTP应答报文离开Server时在OriginateTimeStamp的本地时间。
}NtpPacket;
#endifclass NtpClient : public QObject
{Q_OBJECT
public:explicit NtpClient(QObject *parent = nullptr);void connectServer(QString url);        // 连接Ntp服务void close();void getTime();signals:void updateData(const QString& time);          // 添加显示到界面上文本框中的信息private slots:void on_connected();void on_readData();void sendData();void setDateTime(QDateTime& dateTime);private:QUdpSocket* m_socket = nullptr;
};
#include "ntpclient.h"
#include <QDateTime>
#include <QUdpSocket>
#include <QDebug>
#include <QtEndian>
#include <QElapsedTimer>
#include <QMetaEnum>#ifdef Q_OS_WIN
#include <Windows.h>
#endif
#ifdef Q_OS_LINUX
#include <sys/time.h>
#endifNtpClient::NtpClient(QObject *parent) : QObject(parent)
{m_socket = new QUdpSocket(this);connect(m_socket, &QUdpSocket::connected, this, &NtpClient::on_connected);connect(m_socket, &QUdpSocket::readyRead, this, &NtpClient::on_readData);
}/*** @brief        连接Ntp服务器,端口号默认123* @param url    Ntp服务器IP地址或网址*/
void NtpClient::connectServer(QString url)
{close();m_socket->connectToHost(url, 123);
}void NtpClient::close()
{m_socket->abort();
}void NtpClient::on_connected()
{qDebug() << "连接成功!";QMetaEnum m = QMetaEnum::fromType<QAbstractSocket::SocketState>();      // 获取QUdpSocket连接状态字符串emit updateData(QString("连接成功:%1  %2").arg(m_socket->peerName()).arg(m.key(m_socket->state())));
}void NtpClient::getTime()
{sendData();
}QByteArray toNtpPacket() {QByteArray result(40, 0);quint8 li = 0;                   // LI闰秒标识器,占用2个bit,0 即可;quint8 vn = 3;                   // VN 版本号,占用3个bits,表示NTP的版本号,现在为3;quint8 mode = 3;                 // Mode 模式,占用3个bits,表示模式。 3 表示 client, 2 表示 serverquint8 stratum = 0;              // 系统时钟的层数,取值范围为1~16,它定义了时钟的准确度。层数为1的时钟准确度最高,准确度从1到16依次递减,层数为16的时钟处于未同步状态,不能作为参考时钟。quint8 poll = 4;                 // 轮询时间,即两个连续NTP报文之间的时间间隔(4-14)qint8 precision = -6;            // 系统时钟的精度,精确到秒的平方级(-6 到 -20)result[0] = char((li << 6) | (vn <<3) | (mode));result[1] = char(stratum & 0xff);result[2] = char(poll & 0xff);result[3] = char(precision & 0xff);qint64 currentLocalTimestamp = QDateTime::currentMSecsSinceEpoch();result.append((const char *)&currentLocalTimestamp, sizeof(qint64));return result;
}/*** @brief 发送NTP请求帧*/
void NtpClient::sendData()
{QByteArray arr = toNtpPacket();qint64 len = m_socket->write(arr);if(len != arr.count()){qWarning() << "发送NTP请求帧失败:" << arr.toHex(' ');}
}/*** @brief     将QByteArray类型时间戳数据转换为整形并且进行大小端转换* @param bt* @return*/
quint32 byteToUInt32(QByteArray bt) {if(bt.count() != 4) return 0;quint32 value;memcpy(&value, bt.data(), 4);return qToBigEndian(value);       // 大端转小端
}/*** @brief      将Ntp时间戳转换成QDateTime可用的时间戳* @param bt* @return*/
qint64 byte64ToMillionSecond(QByteArray bt) {qint64 second = byteToUInt32(bt.left(4));qint64 millionSecond = byteToUInt32(bt.mid(4, 4));return (second * 1000L) + ((millionSecond * 1000L) >> 32);
}/*** @brief 接收返回的NTP数据帧并解析*/
void NtpClient::on_readData()
{QElapsedTimer timer;       // 统计数据解析消耗的时间timer.start();QByteArray buf = m_socket->readAll();qint64 currentLocalTimestamp = QDateTime::currentDateTime().toMSecsSinceEpoch();        // 客户端接收到响应报文时的时间戳 T4if(buf.count() < 48)          // Ntp协议帧长度为48字节{return;}QDateTime epoch(QDate(1900, 1, 1), QTime(0, 0, 0));           // ntp时间计时从1900年开始QDateTime unixStart(QDate(1970, 1, 1), QTime(0, 0, 0));       // UNIX操作系统考虑到计算机产生的年代和应用的时限综合取了1970年1月1日作为UNIX TIME的纪元时间(开始时间)qint64 unixDiff = epoch.msecsTo(unixStart);// 解析ntp协议中的时间qint64 referenceTimestamp = byte64ToMillionSecond(buf.mid(16, 8)) - unixDiff;           // 参考时间戳qint64 originTimestamp;                                                                 // 原始时间戳    T1memcpy(&originTimestamp, buf.mid(24, 8), 8);qint64 receiveTimestamp = byte64ToMillionSecond(buf.mid(32, 8)) - unixDiff;             // 接收时间戳   T2qint64 translateTimestamp = byte64ToMillionSecond(buf.mid(40, 8)) - unixDiff;           // 传送时间戳   T3QDateTime dateTime;#if 0qDebug() << "-----------NTP协议中包含的所有时间-----------";dateTime.setMSecsSinceEpoch(referenceTimestamp);qDebug() << "参考时间戳:  " << dateTime.toString("yyyy-MM-dd HH:mm:ss zzz");dateTime.setMSecsSinceEpoch(originTimestamp);qDebug() << "原始时间戳T1:" << dateTime.toString("yyyy-MM-dd HH:mm:ss zzz");dateTime.setMSecsSinceEpoch(receiveTimestamp);qDebug() << "接收时间戳T2:" << dateTime.toString("yyyy-MM-dd HH:mm:ss zzz");dateTime.setMSecsSinceEpoch(translateTimestamp);qDebug() << "传送时间戳T3:" << dateTime.toString("yyyy-MM-dd HH:mm:ss zzz");dateTime.setMSecsSinceEpoch(currentLocalTimestamp);qDebug() << "本地时间戳T4:" << dateTime.toString("yyyy-MM-dd HH:mm:ss zzz");qDebug() << "------------------------------------------";
#endifQString strTime;
#if 1         // 计算方式1:时间差offset=((T2-T1)+(T3-T4))/2      实际时间=程序处理时间(timer.elapsed()) + 接收数据时间T4 + 客户端与服务端的时间差(offset)qint64 currentLocalTimestamp1 = timer.elapsed() + currentLocalTimestamp + qint64((receiveTimestamp - originTimestamp + translateTimestamp - currentLocalTimestamp) / 2);dateTime.setMSecsSinceEpoch(currentLocalTimestamp1);strTime = dateTime.toString("yyyy-MM-dd HH:mm:ss zzz");emit updateData(strTime);
#else        // 计算方式2:往返时延Delay=(T4-T1)-(T3-T2)            实际时间=程序处理时间(timer.elapsed()) + 服务器数据发出时间(T3)+ 通信时延(Delay)qint64 currentLocalTimestamp2 = timer.elapsed() + translateTimestamp + (((currentLocalTimestamp - originTimestamp) - (translateTimestamp - receiveTimestamp)) / 2);dateTime.setMSecsSinceEpoch(currentLocalTimestamp2);strTime = dateTime.toString("yyyy-MM-dd HH:mm:ss zzz");
#endifqDebug() << strTime;setDateTime(dateTime);
}/*** @brief           设置系统时间(注意:这个功能需要使用管理员权限或者超级用户权限)* @param dateTime*/
void NtpClient::setDateTime(QDateTime& dateTime)
{QDate date = dateTime.date();QTime time = dateTime.time();
#ifdef Q_OS_WINSYSTEMTIME system_time = {0};memset(&system_time, 0, sizeof(SYSTEMTIME));system_time.wYear = date.year();system_time.wMonth = date.month();system_time.wDay = date.day();system_time.wHour = time.hour();system_time.wMinute = time.minute();system_time.wSecond = time.second();system_time.wMilliseconds = time.msec();if (SetLocalTime(&system_time))            // 仅限于管理员。{emit updateData("设置时间成功!");}else{emit updateData("设置时间失败!");}
#endif#ifdef Q_OS_LINUXstruct tm tptr;struct timeval tv;tptr.tm_year = date.year() - 1900;            // 这里必须-1900,否则设置不成功tptr.tm_mon = date.month() - 1;               // 月份取值范围为[0-11]tptr.tm_mday = date.day();tptr.tm_hour = time.hour();tptr.tm_min = time.minute();tptr.tm_sec = time.second();tv.tv_sec = mktime(&tptr);                    // 将tptr赋值给tv_sectv.tv_usec = time.msec() * 1000;              // 设置微秒值if (0 == settimeofday(&tv, NULL))            // 仅限于超级用户, 使用sudo ./NtpClient{emit updateData("设置时间成功!");}else{emit updateData("设置时间失败!");}
#endif
}

QT4版本的:

头文件:

#ifndef NTPCLIENT_H
#define NTPCLIENT_H
#include <QUdpSocket>
#include <QObject>
class QUdpSocket;#if 0   // NTP协议帧(未使用)
typedef struct
{char  LI_VN_Mode;char  Stratum;char  Poll;char  Precision;int  RootDelay;int  RootDispersion;int  ReferenceIdentifier;quint64  ReferenceTimeStamp;    // 系统时钟最后一次被设定或更新的时间quint64   OriginateTimeStamp;    // NTP请求报文离开发送端时发送端的本地时间quint64   ReceiveTimeStamp;      // NTP请求报文到达Server端时接收端的本地时间。quint64   TransmitTimeStamp;     // 发送时间戳,客户端发送时填写,server接收到后会将TransmitTimeStamp值写入OriginateTimeStamp,然后NTP应答报文离开Server时在OriginateTimeStamp的本地时间。
}NtpPacket;
#endifclass NtpClient : public QObject
{Q_OBJECT
public:explicit NtpClient(QObject *parent = NULL);void connectServer(QString url);        // 连接Ntp服务void close();void getTime();signals:void updateData(const QString& time);          // 添加显示到界面上文本框中的信息private slots:void on_connected();void on_readData();void sendData();void setDateTime(QDateTime& dateTime);private:QUdpSocket* m_socket;
};#endif // NTPCLIENT_H

源文件:

#include "ntpclient.h"
#include <QDateTime>
#include <QUdpSocket>
#include <QDebug>
#include <QtEndian>
#include <QElapsedTimer>
#include <QMetaEnum>#ifdef Q_OS_WIN
#include <Windows.h>
#endif
#ifdef Q_OS_LINUX
#include <sys/time.h>
#endifNtpClient::NtpClient(QObject *parent) : QObject(parent)
{m_socket = new QUdpSocket(this);connect(m_socket, SIGNAL(connected()), this, SLOT(on_connected()));connect(m_socket, SIGNAL(readyRead()), this, SLOT(on_readData()));
}/*** @brief        连接Ntp服务器,端口号默认123* @param url    Ntp服务器IP地址或网址*/
void NtpClient::connectServer(QString url)
{close();m_socket->connectToHost(url, 123);
}void NtpClient::close()
{m_socket->abort();
}void NtpClient::on_connected()
{qDebug() << "**=======NTP SERVER CONNECT SUCCESS========***!";
//    QMetaEnum m = QMetaEnum::fromType<QAbstractSocket::SocketState>();      // 获取QUdpSocket连接状态字符串 QT5
//    emit updateData(QString("连接成功:%1  %2").arg(m_socket->peerName()).arg(m.key(m_socket->state())));QAbstractSocket::SocketState socketState = m_socket->state();const QMetaObject &mo = QAbstractSocket::staticMetaObject;QMetaEnum me = mo.enumerator(mo.indexOfEnumerator("SocketState"));qDebug()<<me.valueToKey(socketState);emit updateData(QString("连接成功:%1").arg(m_socket->peerName()))/*.arg(me.valueToKey(socketState)))*/;
}void NtpClient::getTime()
{sendData();
}QByteArray toNtpPacket() {QByteArray result(40, 0);quint8 li = 0;                   // LI闰秒标识器,占用2个bit,0 即可;quint8 vn = 3;                   // VN 版本号,占用3个bits,表示NTP的版本号,现在为3;quint8 mode = 3;                 // Mode 模式,占用3个bits,表示模式。 3 表示 client, 2 表示 serverquint8 stratum = 0;              // 系统时钟的层数,取值范围为1~16,它定义了时钟的准确度。层数为1的时钟准确度最高,准确度从1到16依次递减,层数为16的时钟处于未同步状态,不能作为参考时钟。quint8 poll = 4;                 // 轮询时间,即两个连续NTP报文之间的时间间隔(4-14)qint8 precision = -6;            // 系统时钟的精度,精确到秒的平方级(-6 到 -20)result[0] = char((li << 6) | (vn <<3) | (mode));result[1] = char(stratum & 0xff);result[2] = char(poll & 0xff);result[3] = char(precision & 0xff);qint64 currentLocalTimestamp = QDateTime::currentMSecsSinceEpoch();result.append((const char *)&currentLocalTimestamp, sizeof(qint64));return result;
}/*** @brief 发送NTP请求帧*/
void NtpClient::sendData()
{QByteArray arr = toNtpPacket();qint64 len = m_socket->write(arr);if(len != arr.count()){
//        qWarning() << "发送NTP请求帧失败:" << arr.toHex();emit updateData(tr("发送NTP请求帧失败,请先连接服务器或检查连接线路.."));}
}/*** @brief     将QByteArray类型时间戳数据转换为整形并且进行大小端转换* @param bt* @return*/
quint32 byteToUInt32(QByteArray bt) {if(bt.count() != 4) return 0;quint32 value;memcpy(&value, bt.data(), 4);return qToBigEndian(value);       // 大端转小端
}/*** @brief      将Ntp时间戳转换成QDateTime可用的时间戳* @param bt* @return*/
qint64 byte64ToMillionSecond(QByteArray bt) {qint64 second = byteToUInt32(bt.left(4));qint64 millionSecond = byteToUInt32(bt.mid(4, 4));return (second * 1000L) + ((millionSecond * 1000L) >> 32);
}/*** @brief 接收返回的NTP数据帧并解析*/
void NtpClient::on_readData()
{QElapsedTimer timer;       // 统计数据解析消耗的时间timer.start();QByteArray buf = m_socket->readAll();qint64 currentLocalTimestamp = QDateTime::currentDateTime().toMSecsSinceEpoch();        // 客户端接收到响应报文时的时间戳 T4if(buf.count() < 48)          // Ntp协议帧长度为48字节{return;}QDateTime epoch(QDate(1900, 1, 1), QTime(0, 0, 0));           // ntp时间计时从1900年开始QDateTime unixStart(QDate(1970, 1, 1), QTime(0, 0, 0));       // UNIX操作系统考虑到计算机产生的年代和应用的时限综合取了1970年1月1日作为UNIX TIME的纪元时间(开始时间)qint64 unixDiff = epoch.msecsTo(unixStart);// 解析ntp协议中的时间qint64 referenceTimestamp = byte64ToMillionSecond(buf.mid(16, 8)) - unixDiff;           // 参考时间戳qint64 originTimestamp;                                                                 // 原始时间戳    T1memcpy(&originTimestamp, buf.mid(24, 8), 8);qint64 receiveTimestamp = byte64ToMillionSecond(buf.mid(32, 8)) - unixDiff;             // 接收时间戳   T2qint64 translateTimestamp = byte64ToMillionSecond(buf.mid(40, 8)) - unixDiff;           // 传送时间戳   T3QDateTime dateTime,dateTimeDiff8;#if 1qDebug() << "-----------NTP协议中包含的所有时间-----------";dateTime.setMSecsSinceEpoch(referenceTimestamp);qDebug() << "参考时间戳:  " << dateTime.toString("yyyy-MM-dd HH:mm:ss zzz");dateTime.setMSecsSinceEpoch(originTimestamp);qDebug() << "原始时间戳T1:" << dateTime.toString("yyyy-MM-dd HH:mm:ss zzz");dateTime.setMSecsSinceEpoch(receiveTimestamp);qDebug() << "接收时间戳T2:" << dateTime.toString("yyyy-MM-dd HH:mm:ss zzz");dateTime.setMSecsSinceEpoch(translateTimestamp);qDebug() << "传送时间戳T3:" << dateTime.toString("yyyy-MM-dd HH:mm:ss zzz");dateTime.setMSecsSinceEpoch(currentLocalTimestamp);qDebug() << "本地时间戳T4:" << dateTime.toString("yyyy-MM-dd HH:mm:ss zzz");qDebug() << "------------------------------------------";
#endifQString strTime;
#if 0         // 计算方式1:时间差offset=((T2-T1)+(T3-T4))/2      实际时间=程序处理时间(timer.elapsed()) + 接收数据时间T4 + 客户端与服务端的时间差(offset)qint64 currentLocalTimestamp1 = timer.elapsed() + currentLocalTimestamp + qint64((receiveTimestamp - originTimestamp + translateTimestamp - currentLocalTimestamp) / 2);dateTime.setMSecsSinceEpoch(currentLocalTimestamp1);strTime = dateTime.toString("yyyy-MM-dd HH:mm:ss zzz");//UTC --> LOCALtimeQDateTime utc_from_str = QDateTime::fromString(strTime,Qt::ISODate);QDateTime utc_to_local = utc_from_str.toLocalTime();strTime = utc_to_local.toString("yyyy-MM-dd HH:mm:ss zzz");emit updateData(strTime);
#else        // 计算方式2:往返时延Delay=(T4-T1)-(T3-T2)            实际时间=程序处理时间(timer.elapsed()) + 服务器数据发出时间(T3)+ 通信时延(Delay)qint64 currentLocalTimestamp2 = timer.elapsed() + translateTimestamp + (((currentLocalTimestamp - originTimestamp) - (translateTimestamp - receiveTimestamp)) / 2);dateTime.setMSecsSinceEpoch(currentLocalTimestamp2);dateTimeDiff8 = dateTime.addSecs(60*60*8); //解决时区问题加8个小时,个人平台问题加的,正常是不需要做处理的strTime = dateTimeDiff8.toString("yyyy-MM-dd HH:mm:ss zzz");
//    //UTC --> LOCALtime
//    QDateTime utc_from_str = QDateTime::fromString(strTime,Qt::ISODate);
//    QDateTime utc_to_local = utc_from_str.toLocalTime();
//    strTime = utc_to_local.toString("yyyy-MM-dd HH:mm:ss zzz");emit updateData(strTime);
#endifqDebug() << strTime;
//    QString tmp = QString("date -s '%1'").arg(strTime);
//    system(tmp.toLatin1().data());setDateTime(dateTimeDiff8);system("hwclock -w");system("sync");
}/*** @brief           设置系统时间(注意:这个功能需要使用管理员权限或者超级用户权限)* @param dateTime*/
void NtpClient::setDateTime(QDateTime& dateTime)
{QDate date = dateTime.date();QTime time = dateTime.time();
#ifdef Q_OS_WINSYSTEMTIME system_time = {0};memset(&system_time, 0, sizeof(SYSTEMTIME));system_time.wYear = date.year();system_time.wMonth = date.month();system_time.wDay = date.day();system_time.wHour = time.hour();system_time.wMinute = time.minute();system_time.wSecond = time.second();system_time.wMilliseconds = time.msec();if (SetLocalTime(&system_time))            // 仅限于管理员。{emit updateData(tr("设置时间成功!"));}else{emit updateData(tr("设置时间失败!"));}
#endif#ifdef Q_OS_LINUXstruct tm tptr;struct timeval tv;tptr.tm_year = date.year() - 1900;            // 这里必须-1900,否则设置不成功tptr.tm_mon = date.month() - 1;               // 月份取值范围为[0-11]tptr.tm_mday = date.day();tptr.tm_hour = time.hour();tptr.tm_min = time.minute();tptr.tm_sec = time.second();tv.tv_sec = mktime(&tptr);                    // 将tptr赋值给tv_sectv.tv_usec = time.msec() * 1000;              // 设置微秒值if (0 == settimeofday(&tv, NULL))            // 仅限于超级用户, 使用sudo{emit updateData(tr("设置时间成功!"));}else{emit updateData(tr("设置时间失败!"));}
#endif
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/31768.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AI作曲】毁掉音乐?早该来了!一个网易音乐人对于 AI 大模型音乐创作的思辨

引言&#xff1a;AI在创造还是毁掉音乐&#xff1f; 正如当初 midjourney 和 StableDiffusion 在绘画圈掀起的风波一样&#xff0c;suno 和 各大音乐大模型的来临&#xff0c;其实早该来了。 AI 在毁掉绘画&#xff1f;或者毁掉音乐&#xff1f; 没错&#xff0c;但也错了。…

MGV电源维修KUKA机器人电源模块PH2003-4840

MGV电源维修 库卡电源模块维修 机器人电源模块维修 库卡控制器维修 KUKA电源维修 库卡机器人KUKA主机维修 KUKA驱动器模块维修 机械行业维修&#xff1a;西门子系统、法那克系统、沙迪克、FIDIA、天田、阿玛达、友嘉、大宇系统&#xff1b;数控冲床、剪板机、折弯机等品牌数控…

语音相关算法学习整理

最近看了一下百度paddlespeech的一些公开课&#xff0c;把课程里的视频内容大体听了一下&#xff0c;现在整理一下笔记。教程链接见&#xff1a;飞桨AI Studio星河社区-人工智能学习与实训社区 语音识别的过程可以这样简单概括&#xff1a; 将声音信号经过预加重、加窗、fft等…

JavaWeb——Mysql的启动/登录/卸载

目录 1.Mysql服务器 2.Mysql的简单使用 2.1 启动Mysql&#xff1a; 2.2 登录Mysql 2.3 退出 3. 连接别人的数据库 4.卸载mqsql 1.Mysql服务器 安装了Mysql的计算机都成为Mysql服务器 2.Mysql的简单使用 2.1 启动Mysql&#xff1a; 第一种方法&#xff1a;搜索服务&am…

如何在微信小程序使用vant 进行自定义底部tabbar组件

在微信小程序中使用 Vant 自定义底部 TabBar 需要进行以下步骤&#xff1a; 一、首先&#xff0c;你需要在 app.json 文件中配置自定义 TabBar。 在 "tabBar" 字段中&#xff0c;设置 "custom" 为 true&#xff0c;表示使用自定义 TabBar。 app.json示例…

python18 正则表达式

python18 正则表达式 正则表达式 re.match(),re.search(),re.findall(),re.sub(),re.split() 元字符 具有特殊意义的专用字符 导入模块 improt re代码 正则表达式 re.match(),re.search(),re.findall(),re.sub(),re.split() 元字符 具有特殊意义的专用字符 导入模块 improt rei…

AQS和同步器工具类

一、 同步框架AbstractQueuedSynchronizer Java并发编程核心在于java.concurrent.util包 而juc当中的大多数同步器实现都是围绕着共同的基础行为&#xff0c;比如等待队列、条件队列、独占获取、共享获取等&#xff0c;而这个行为的抽象就是基于AbstractQueuedSynchronizer简称…

关于多线程的理解

#系列文章 关于时间复杂度o(1), o(n), o(logn), o(nlogn)的理解 关于HashMap的哈希碰撞、拉链法和key的哈希函数设计 关于JVM内存模型和堆内存模型的理解 关于代理模式的理解 关于Mysql基本概念的理解 关于软件设计模式的理解 关于Redis知识的理解 文章目录 前言一、线程…

Docker基本使用和认识

目录 基本使用 镜像仓库 镜像操作 Docker 如何实现镜像 1) namespace 2) cgroup 3) LXC Docker常见的网络类型 bridge网络如何实现 基本使用 镜像仓库 镜像仓库登录 1)docker login 后面不指定IP地址&#xff0c;则默认登录到 docker hub 上 退出 2)docker logo…

P5711 【深基3.例3】闰年判断

1. 题目链接 https://www.luogu.com.cn/problem/P5711 P5711 【深基3.例3】闰年判断 2. 题目描述 题目描述&#xff1a;判断一个数是否是闰年 输入&#xff1a;输入一个整数n 输出&#xff1a;输出1或0&#xff0c;如果是闰年&#xff0c;输出1&#xff0c;否则输出0 3. 我的…

大数据经典sql

一、连续登录问题 问题&#xff1a;1&#xff09;、每个用户连续登录最大天数 2&#xff09;、连续登录大于三天的用户数 分析&#xff1a;本质都是计算用户连续登录天数 方案一&#xff1a;利用排序窗口 select a.user_id,a.date_rslt,count(1) as cnt from (select t.…

进入容器修改内容_提交改变后的镜像_镜像保存成tar压缩包离线传输_镜像传输_镜像推送到公共仓库---分布式云原生部署架构搭建009

然后再来看,进入docker内部去看看. 用 docker exec -it imgid /bin/bash 这样就可以进入容器内部 而且关于,镜像的,内部放到什么地方了,都可以找到比如 在hub.docker的地址里面,找到nginx可以看到,对应的 /usr/share/nginx/html 可以看到这个路径. 然后去看看,进入到/usr…

Android 数据库

帮助类对象中的getWritableDatabase 和 getReadableDatabase都可以帮助我们获取一个数据库操作对象SqliteDatabase. 区别&#xff1a; getReadableDatabase: 先尝试以读写方式打开数据库&#xff0c;如果磁盘空间满了&#xff0c;他会重新尝试以只读方式打开数据库。 getWr…

如何恢复未格式化分区数据?看这里!

什么是未格式化分区&#xff1f; 未格式化或RAW文件系统的分区无法被Windows操作系统识别和挂载&#xff0c;因此&#xff0c;Windows会提示你进行格式化以创建新的文件系统。注意&#xff0c;不要进行格式化。通常&#xff0c;文件系统变为未格式化或RAW会出现以下常见错误消…

专业VS学校:高考后的选择困境与解决之道

随着2024年高考的落幕&#xff0c;数百万考生站在了人生新的十字路口。分数的揭晓&#xff0c;既是对过往努力的肯定&#xff0c;也带来了新的选择难题。在专业与学校的权衡中&#xff0c;考生们往往陷入两难&#xff1a;是追随内心选择心仪的专业&#xff0c;还是选择一个知名…

大学选专业还是选学校好 哪个更重要

​​​​​​​如果你的分数不理想&#xff0c;建议先选专业。如果你是高分考生&#xff0c;建议先选学校。具体来看一下&#xff01; 选专业还是选学校好 如果你是高分考生&#xff0c;建议先选学校 1 可以借助学校的名气 我们都知道&#xff0c;学校越有名&#xff0c;能…

(深度学习记录)第TR5周:Transformer中的位置编码详解

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 &#x1f3e1;我的环境&#xff1a; 语言环境&#xff1a;Python3.11.4编译器&#xff1a;Jupyter Notebooktorcch版本&#xff1a;2.0.…

【Matlab编程学习】 | matlab语言编程基础:常用图形绘制基础学习

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

传输层udp和tcp协议格式

UDP协议 UDP协议端格式 udp的前八个字节是报头&#xff0c;后面部分就是有效载荷。而目的端口号就保证了udp向应用层交付的问题。 而针对于报头和有效载荷分离是根据固定八字结的报头长度。数据的长度就是取决于报头中udp长度字段的大小来确定udp报文长度&#xff0c;因此也可…

Apifox 中如何处理加密或编码过的响应数据?

接口返回的响应数据有时是经过编码或加密处理的&#xff0c;要转换成可读的明文&#xff0c;可以使用 Apifox 内置的 JS 类库、或者通过调用外部编程语言 &#xff08;如 Python、JavaScript 等&#xff09; 来进行处理。 例如&#xff0c;一个经过 Base64 编码的数据可以通过…