当前位置: 首页 > news >正文

《TCP/IP网络编程》学习笔记 | Chapter 7:优雅地断开套接字连接

《TCP/IP网络编程》学习笔记 | Chapter 7:优雅地断开套接字连接

  • 《TCP/IP网络编程》学习笔记 | Chapter 7:优雅地断开套接字连接
    • 基于 TCP 的半关闭
      • 单方面断开连接带来的问题
      • 套接字和流
      • 针对优雅断开的 shutdown 函数
      • 为何需要半关闭?
      • 基于半关闭的文件传输程序
    • 基于 Windows 的实现
      • Windows 下的 shutdown 函数
      • 基于 Windows 的半关闭文件传输程序
    • 习题
      • (1)解释 TCP 中 “流” 的概念。UDP 中能否形成流?请说明原因。
      • (2)Linux 中的 close 函数或 Windows 中的closesocket函数属于单方面断开连接的方法,有可能带来一些问题。什么是单方面断开连接?什么情况下会出现问题?
      • (3)什么是半关闭?针对输出流执行半关闭的主机处于何种状态?半关闭会导致对方主机接收什么信息?

《TCP/IP网络编程》学习笔记 | Chapter 7:优雅地断开套接字连接

基于 TCP 的半关闭

单方面断开连接带来的问题

Linux 中的 close 与 Windows 中的 closesocket 函数意味着完全断开连接,完全断开后,套接字既无法传输数据,也无法接收数据。

在这里插入图片描述

如上图所示,主机A断开连接后,再也无法接受主机B传输的数据,最终主机B传输的数据只能销毁。

为了解决这一问题,在关闭连接时,只关闭流的一部分(半关闭),即可以传输数据但不能接受数据,或者可以接收数据但不能传输数据。

套接字和流

一旦两台主机建立了套接字连接,每个主机就会拥有单独的输入流与输出流。一个主机的输入流与另一台主机的输出流相连,输出流与另一台主机的输入流相连。

在这里插入图片描述

Linux 中的 close 与 Windows 中的 closesocket 函数将同时断开这两个流。

针对优雅断开的 shutdown 函数

半关闭函数:

#include <sys/socket.h>int shutdown(int sock, int howto);

成功时返回 0,失败时返回 -1。

参数:

  • sock:需要断开的套接字文件描述符。
  • howto:断开方式信息。其有 3 种可能值。SHUT_RD:断开输入流;SHUT_WR:断开输出流;SHUT_RDWR:同时断开 I/O 流。

SHUT_RD,SHUT_WR,SHUT_RDWR 的值按序分别是 0,1,2。若向 shutdown 的第二个参数传递SHUT_RD,则断开输入流,套接字无法接收数据。即使输入缓冲收到数据也会抹去,而且无法调用输入相关函数。如果向 shutdown 的第二个参数传递SHUT_WR,则中断输出流,也就无法传输数据。若如果输出缓冲中还有未传输的数据,则将传递给目标主机。最后,若传递关键字SHUT_RDWR,则同时中断 I/O 流。这相当于分 2 次调用 shutdown ,其中一次以SHUT_RD为参数,另一次以SHUT_WR为参数。

为何需要半关闭?

  1. 数据传输完成: 当一方已经发送完所有需要发送的数据,但仍然需要接收对方的响应或数据时,可以使用半关闭。这样,发送方可以告诉对方已经没有更多的数据要发送了。
  2. 错误处理: 如果一方在通信过程中遇到错误,它可能会选择关闭发送方向,以防止发送更多的数据,同时仍然监听对方可能发送的错误响应或状态信息。
  3. 保持连接: 在某些应用场景中,即使数据传输已经完成,一方可能仍希望保持连接,以便在将来需要时重新使用,而不是重新建立连接。
  4. 优雅地关闭连接: 在TCP连接中,半关闭允许一方在发送完所有数据后优雅地关闭连接,而不是突然断开,这有助于另一方正确地处理连接的关闭。
  5. 调试和诊断: 在调试网络应用程序时,半关闭可以帮助开发者理解数据流和连接状态,从而更容易地诊断问题。

比如服务器给客户端发数据,发完后客户端回一个 “Thank you”,但客户端不知道什么时候发完,所以需要一直调用 read() 函数。

改进1:可以在发完数据后服务器向客户端发送EOF表示发送结束。

问题:服务器调用 close() 函数关闭连接并发送 EOF 后,输入流也断了,客户端发的 “Thank you” 将无法收到。

改进2:调用 shutdown() 函数只关闭服务器的输入流就行了。

基于半关闭的文件传输程序

协议示意图:

在这里插入图片描述

服务器端的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 30;void error_handling(char *message);int main(int argc, char *argv[])
{int serv_sd, clnt_sd;FILE *fp;char buf[BUF_SIZE];int read_cnt;struct sockaddr_in serv_addr, clnt_addr;socklen_t clnt_addr_sz;if (argc != 2){printf("Usage: %s <port>\n", argv[0]);exit(1);}fp = fopen("file_server.c", "rb");serv_sd = socket(PF_INET, SOCK_STREAM, 0);memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port = htons(atoi(argv[1]));bind(serv_sd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));listen(serv_sd, 5);clnt_addr_sz = sizeof(clnt_addr);clnt_sd = accept(serv_sd, (struct sockaddr *)&clnt_addr, &clnt_addr_sz);while (1){read_cnt = fread((void *)buf, 1, BUF_SIZE, fp);if (read_cnt < BUF_SIZE){write(clnt_sd, buf, read_cnt);break;}write(clnt_sd, buf, BUF_SIZE);}shutdown(clnt_sd, SHUT_WR);read(clnt_sd, buf, BUF_SIZE);printf("Message from client: %s \n", buf);fclose(fp);close(clnt_sd);close(serv_sd);return 0;
}void error_handling(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}

客户端的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 30void error_handling(char *message);int main(int argc, char *argv[])
{int sd;FILE *fp;char buf[BUF_SIZE];int read_cnt;struct sockaddr_in serv_addr;if (argc != 3){printf("Usage: %s <IP> <port>\n", argv[0]);exit(1);}fp = fopen("receive.dat", "wb");sd = socket(PF_INET, SOCK_STREAM, 0);memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr(argv[1]);serv_addr.sin_port = htons(atoi(argv[2]));connect(sd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));while ((read_cnt = read(sd, buf, BUF_SIZE)) != 0)fwrite((void *)buf, 1, read_cnt, fp);puts("Received file data");write(sd, "Thank you", 10);fclose(fp);close(sd);return 0;
}void error_handling(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}

基于 Windows 的实现

Windows 下的 shutdown 函数

#include <winsock2.h>int shutdown(SOCKET s, int howto);

成功时返回 0,失败时返回 SOCKET_ERROR。

参数:

  • s:要断开的套接字的句柄。
  • howto:断开方式信息。其有 3 种可能值。SHUT_RECEIVE:断开输入流;SHUT_SEND:断开输出流;SHUT_BOTH:同时断开 I/O 流。其值按序分别是 0,1,2。

基于 Windows 的半关闭文件传输程序

file_server_win.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>#define BUF_SIZE 30void ErrorHanding(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[])
{WSADATA wsaData;SOCKET serverSock, clientSock;SOCKADDR_IN serverAddr, clientAddr;int clientAddrSize;int read_cnt;char file_name[] = "file_server_win.c";char buf[BUF_SIZE];if (argc != 2){printf("Usage: %s <port>\n", argv[0]);exit(1);}if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)ErrorHanding("WSAStartup() error!");serverSock = socket(PF_INET, SOCK_STREAM, 0);if (serverSock == INVALID_SOCKET)ErrorHanding("socket() error!");memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);serverAddr.sin_port = htons(atoi(argv[1]));if (bind(serverSock, (SOCKADDR *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)ErrorHanding("bind() error!");if (listen(serverSock, 5) == SOCKET_ERROR)ErrorHanding("listen() error!");clientAddrSize = sizeof(clientAddr);clientSock = accept(serverSock, (SOCKADDR *)&clientAddr, &clientAddrSize);if (clientSock == INVALID_SOCKET)ErrorHanding("accept() error!");FILE *fp = fopen(file_name, "rb");if (fp != NULL){while (1){read_cnt = fread((void *)buf, 1, BUF_SIZE, fp);if (read_cnt < BUF_SIZE){send(clientSock, (char *)&buf, read_cnt, 0);break;}elsesend(clientSock, (char *)&buf, BUF_SIZE, 0);}}shutdown(clientSock, SD_SEND);recv(clientSock, (char *)buf, BUF_SIZE, 0);printf("Message from client: %s\n", buf);fclose(fp);closesocket(clientSock);closesocket(serverSock);WSACleanup();return 0;
}

file_client_win.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>#define BUF_SIZE 30void ErrorHanding(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[])
{WSADATA wsaData;SOCKET sock;SOCKADDR_IN serverAddr;int read_cnt;char file_name[] = "receive.dat";char buf[BUF_SIZE];if (argc != 3){printf("Usage: %s <IP> <port>\n", argv[0]);exit(1);}if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)ErrorHanding("WSAStartup() error!");sock = socket(PF_INET, SOCK_STREAM, 0);if (sock == INVALID_SOCKET)ErrorHanding("sock() error!");memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = inet_addr(argv[1]);serverAddr.sin_port = htons(atoi(argv[2]));if (connect(sock, (SOCKADDR *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)ErrorHanding("connect() error!");FILE *fp = fopen(file_name, "wb");while ((read_cnt = recv(sock, buf, BUF_SIZE, 0)) != 0)fwrite((void *)buf, 1, read_cnt, fp);printf("Received file data\n");send(sock, "Thank you", 10, 0);fclose(fp);closesocket(sock);WSACleanup();return 0;
}

编译:

gcc file_server_win.c -lwsock32 -o fileServWin
gcc file_client_win.c -lwsock32 -o fileClntWin

运行结果:

// 服务器端
C:\Users\81228\Documents\Program\TCP IP Project\Chapter 7>fileServWin 9190
Message from client: Thank you
// 客户端
C:\Users\81228\Documents\Program\TCP IP Project\Chapter 7>fileClntWin 127.0.0.1 9190
Received file data

接收到的文件 receive.dat 里面的内容就是 file_server_win.c,这里只展示部分内容:

在这里插入图片描述

习题

(1)解释 TCP 中 “流” 的概念。UDP 中能否形成流?请说明原因。

TCP的流是指,两台主机通过套接字建立连接后进入可交换数据的状态,也称为“流形成的状态”。也就是把建立套接字后可交换数据的状态看做一种流。

UDP是基于报文面向无连接的,没有建立连接的过程,所以不能形成流。

(2)Linux 中的 close 函数或 Windows 中的closesocket函数属于单方面断开连接的方法,有可能带来一些问题。什么是单方面断开连接?什么情况下会出现问题?

单方面断开连接就是两台主机正在通信,其中一台主机关闭了所有连接,那么一台主机向另一台主机传输的数据可能会没有接收到而损毁。

单方面的断开连接意味着套接字无法再发送数据。一般在对方有剩余数据未发送完成时,断开己方连接,会造成问题。

(3)什么是半关闭?针对输出流执行半关闭的主机处于何种状态?半关闭会导致对方主机接收什么信息?

半关闭就是把输入流或者输出流关了。

针对输出流执行半关闭的主机处于可以接收数据而不能发送数据。

半关闭会使其​发送最后一个报文段时附带一个EOF,告诉对方主机自己没有数据要发了,但还是可以接收对方主机传送的数据。

相关文章:

《TCP/IP网络编程》学习笔记 | Chapter 7:优雅地断开套接字连接

《TCP/IP网络编程》学习笔记 | Chapter 7&#xff1a;优雅地断开套接字连接 《TCP/IP网络编程》学习笔记 | Chapter 7&#xff1a;优雅地断开套接字连接基于 TCP 的半关闭单方面断开连接带来的问题套接字和流针对优雅断开的 shutdown 函数为何需要半关闭&#xff1f;基于半关闭…...

Anaconda 和 conda 是什么关系?就像 pip 和 python 一样吗

Anaconda 和 conda是 Anaconda Distribution 还是 Miniconda Anaconda 和 conda Anaconda 和 conda 之间的关系有点类似于 pip 和 Python&#xff0c;但又有所不同。 Anaconda 是一个数据科学和机器学习的发行版&#xff0c;它包含了 Python、conda 以及许多预装的库和工具&am…...

「数据治理」核心专业术语解释!

​数据治理就是指在一定的组织范围内&#xff0c;依托制度法规、标准规范、应用实践和支撑技术对数据进行全生命周期的数据确权、质量管理、安全控制、隐私保护、开放共享、交易流通和分析处理。数据治理的目标是为了提高数据的可用性、安全性、流通性&#xff0c;激活数据资源…...

Mac Nginx 前端打包部署

安装homebrew /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 安装Nginx brew install nginx nginx相关命令 nginx启动命令&#xff1a;nginx nginx -s reload #重新加载配置 nginx -s reopen #重启 nginx -s stop #…...

乳腺癌诊断分析——基于聚类分析实现

一、研究背景 乳腺癌属于恶性肿瘤&#xff0c;在早期发现后需要及早将病变组织切除&#xff0c;而且术后还要化疗和放射等辅助治疗&#xff0c;能够抑制癌细胞的扩散和增长。 二、研究目的 研究乳腺癌病人的患病特征通过聚类分析方法对特征进行分类通过上述聚类结果对乳腺诊…...

Ubuntu 22.04 安装配置opencv

​ OpenCV下载:https://opencv.org/releases/ ​编译与安装 安装cmake OpenCV需要使用cmake进行编译 sudo apt-get install cmake安装依赖 sudo apt-get install build-essential pkg-config libgtk2.0-dev libavcodec-dev libavformat-dev libjpeg-dev libswscale-dev lib…...

【软考】系统架构设计师-计算机系统基础(3):嵌入式系统

嵌入式系统&#xff1a;嵌入式处理器、相关支撑硬件、嵌入式OS、支撑软件以及应用软件 嵌入式系统特征&#xff1a;专用性强、技术融合、软硬一体软件为主、通用计算机资源少,... 分层&#xff08;5层&#xff09;&#xff1a;硬件层 → 抽象层 → 操作系统层 → 中间件层 →…...

实测运行容器化Tomcat服务器

文章目录 前言一、拉取Tomcat 9.0镜像二、运行容器化Tomcat服务器三、访问Tomcat官网首页测试 总结 前言 运行容器化Tomcat服务器&#xff0c;首先确保正确安装docker&#xff0c;并且已启动运行&#xff0c;具体安装docker方法见笔者前面的博文《OpenEuler 下 Docker 安装、配…...

致敬苹果的国产手机,只会失去更多市场,iPhone一骑绝尘!

近期诸多国产手机品牌纷纷发布旗舰手机&#xff0c;随着这些旗舰手机的发布&#xff0c;可以看出他们在进一步致敬苹果--实质就是模仿苹果的设计&#xff0c;如此做的结果恐怕是得不偿失&#xff0c;将导致国产手机损失更多市场。 致敬苹果最为直接的当属手机外壳了&#xff0c…...

《MYSQL45讲》kill不掉的线程

kill query 线程id :终止这个线程正在执行的语句 kill connection 线程id :关闭这个线程的连接&#xff0c;也会先停止这个线程正在执行的语句。这个connection可以缺省。 本文讨论的情况是&#xff1a;使用了kill命令&#xff0c;却没有断开连接&#xff0c;show processli…...

单体架构 IM 系统之 Server 节点状态化分析

基于 http 短轮询模式的单体架构的 IM 系统见下图&#xff0c;即客户端通过 http 周期性地轮询访问 server 实现消息的即时通讯&#xff0c;也就是我们前面提到的 “信箱模型”。“信箱模型” 虽然实现非常容易&#xff0c;但是消息的实时性不高。 我们在上一篇文章&#xff08…...

java xml 文本解析

示例文本 <Message><MessageName>time_request</MessageName><Timestamp>20220217165432906359</Timestamp><Body><EQPID>CMMAB01-DTP01</EQPID></Body> </Message>示例代码 import org.w3c.dom.Document; impo…...

Docker占用空间太大磁盘空间不足清理妙招

docker占用空间太大了&#xff0c;磁盘空间不足&#xff0c;清理3妙招 清除所有已停止的容器&#xff08;container&#xff09;、未被任何容器所使用的卷&#xff08;volume&#xff09;、未被任何容器所关联的网络&#xff08;network&#xff09;、所有悬空镜像&#xff08…...

编程之路,从0开始:字符函数和字符串函数

Hello大家好&#xff01;很高兴我们又见面了&#xff01; 给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 目录 1、字符分类函数 2、字符转换函数 3、字符串函数 1、 strcpy 2、 strcat 3、 strcmp 4、strlen(s) 5、strstr(s1, s2) 6、 strtok(s1, s2…...

化工防爆巡检机器人:在挑战中成长,为化工安全保驾护航

随着全球能源需求的不断攀升&#xff0c;化工行业的安全性与高效性愈发受到关注。化工设施规模巨大&#xff0c;而且其中多数存在高风险因素&#xff0c;像是易燃易爆化学物质、高温环境、有毒有害物质以及高压设备等。仅2023年&#xff0c;国内危化品事故就多达652起&#xff…...

音频采样数据格式

音频信号在模拟到数字转换时&#xff0c;会涉及到多个关键参数&#xff0c;如采样率、位深度、通道数等。下面是常见的音频采样数据格式及其相关概念&#xff1a; 1. 采样率 (Sample Rate) 采样率指的是每秒钟对音频信号进行采样的次数&#xff0c;单位为赫兹 (Hz)。常见的值…...

【pytorch】常用强化学习算法实现(持续更新)

持续更新常用的强化学习算法&#xff0c;采用单python文件实现&#xff0c;简单易读 2024.11.09 更新&#xff1a;PPO(GAE); SAC2024.11.12 更新&#xff1a;OptionCritic(PPOC) "PPO" import copy import time import torch import numpy as np import torch.nn as …...

DAY59||并查集理论基础 |寻找存在的路径

并查集理论基础 并查集主要有两个功能&#xff1a; 将两个元素添加到一个集合中。判断两个元素在不在同一个集合 代码模板 int n 1005; // n根据题目中节点数量而定&#xff0c;一般比节点数量大一点就好 vector<int> father vector<int> (n, 0); // C里的一…...

Mybatis执行自定义SQL并使用PageHelper进行分页

Mybatis执行自定义SQL并使用PageHelper进行分页 基于Mybatis&#xff0c;让程序可以执行动态传入的SQL&#xff0c;而不需要在xml或者Select语句中定义。 代码示例 pom.xml 依赖 <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId&g…...

OpenCV DNN

OpenCV DNN 和 PyTorch 都是常用的深度学习框架&#xff0c;但它们的定位、使用场景和功能有所不同。让我们来对比一下这两个工具&#xff1a; 1. 框架和功能 OpenCV DNN&#xff1a;OpenCV DNN 模块主要用于加载和运行已经训练好的深度学习模型&#xff0c;支持多种深度学习…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

MyBatis中关于缓存的理解

MyBatis缓存 MyBatis系统当中默认定义两级缓存&#xff1a;一级缓存、二级缓存 默认情况下&#xff0c;只有一级缓存开启&#xff08;sqlSession级别的缓存&#xff09;二级缓存需要手动开启配置&#xff0c;需要局域namespace级别的缓存 一级缓存&#xff08;本地缓存&#…...

CppCon 2015 学习:Time Programming Fundamentals

Civil Time 公历时间 特点&#xff1a; 共 6 个字段&#xff1a; Year&#xff08;年&#xff09;Month&#xff08;月&#xff09;Day&#xff08;日&#xff09;Hour&#xff08;小时&#xff09;Minute&#xff08;分钟&#xff09;Second&#xff08;秒&#xff09; 表示…...