《TCP IP网络编程》第十三章
第 13 章 多种 I/O 函数
13.1 send & recv 函数
Linux 中的 send & recv:
send 函数定义:
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t nbytes, int flags);
/*
成功时返回发送的字节数,失败时返回 -1
sockfd: 表示与数据传输对象的连接的套接字和文件描述符
buf: 保存待传输数据的缓冲地址值
nbytes: 待传输字节数
flags: 传输数据时指定的可选项信息
*/
recv 函数的定义:
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t nbytes, int flags);
/*
成功时返回接收的字节数(收到 EOF 返回 0),失败时返回 -1
sockfd: 表示数据接受对象的连接的套接字文件描述符
buf: 保存接受数据的缓冲地址值
nbytes: 可接收的最大字节数
flags: 接收数据时指定的可选项参数
*/
send 和 recv 函数的最后一个参数是收发数据的可选项,该选项可以用位或(bit OR)运算符(| 运算符)同时传递多个信息。send & recv 函数的可选项意义:

MSG_OOB:发送紧急消息 :
MSG_OOB 可选项用于创建特殊发送方法和通道以发送紧急消息。下面为 MSG_OOB 的示例代码:
recv:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>#define BUF_SIZE 30
void error_handling(char *message);
void urg_handler(int signo);int acpt_sock;
int recv_sock;int main(int argc, char *argv[])
{struct sockaddr_in recv_adr, serv_adr;int str_len, state;socklen_t serv_adr_sz;struct sigaction act;char buf[BUF_SIZE];if (argc != 2){printf("Usage : %s <port>\n", argv[0]);exit(1);}act.sa_handler = urg_handler;sigemptyset(&act.sa_mask);act.sa_flags = 0;acpt_sock = socket(PF_INET, SOCK_STREAM, 0);memset(&recv_adr, 0, sizeof(recv_adr));recv_adr.sin_family = AF_INET;recv_adr.sin_addr.s_addr = htonl(INADDR_ANY);recv_adr.sin_port = htons(atoi(argv[1]));if (bind(acpt_sock, (struct sockaddr *)&recv_adr, sizeof(recv_adr)) == -1)error_handling("bind() error");listen(acpt_sock, 5);serv_adr_sz = sizeof(serv_adr);recv_sock = accept(acpt_sock, (struct sockaddr *)&serv_adr, &serv_adr_sz);//文件描述符 recv_sock 指向的套接字引发的 SIGURG 信号处理进程变为 getpid 函数返回值用作 ID 进程.fcntl(recv_sock, F_SETOWN, getpid());state = sigaction(SIGURG, &act, 0); //SIGURG 是一个信号,当接收到 MSG_OOB 紧急消息时,系统产生SIGURG信号while ((str_len = recv(recv_sock, buf, sizeof(buf), 0)) != 0){if (str_len == -1)continue;buf[str_len] = 0;puts(buf);}close(recv_sock);close(acpt_sock);return 0;
}
void urg_handler(int signo)
{int str_len;char buf[BUF_SIZE];str_len = recv(recv_sock, buf, sizeof(buf) - 1, MSG_OOB);buf[str_len] = 0;printf("Urgent message: %s \n", buf);
}void error_handling(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}
send:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>#define BUF_SIZE 30
void error_handling(char *message);int main(int argc, char *argv[])
{int sock;struct sockaddr_in recv_adr;if (argc != 3){printf("Usage : %s <IP> <port>\n", argv[0]);exit(1);}sock = socket(PF_INET, SOCK_STREAM, 0);memset(&recv_adr, 0, sizeof(recv_adr));recv_adr.sin_family = AF_INET;recv_adr.sin_addr.s_addr = inet_addr(argv[1]);recv_adr.sin_port = htons(atoi(argv[2]));if (connect(sock, (struct sockaddr *)&recv_adr, sizeof(recv_adr)) == -1)error_handling("connect() error");write(sock, "123", strlen("123"));send(sock, "4", strlen("4"), MSG_OOB);write(sock, "567", strlen("567"));send(sock, "890", strlen("890"), MSG_OOB);close(sock);return 0;
}void error_handling(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}

输出结果,可能出乎意料:
通过 MSG_OOB 可选项传递数据时只返回 1 个字节,而且也不快
的确,通过 MSG_OOB 并不会加快传输速度,而通过信号处理函数 urg_handler 也只能读取一个字节。剩余数据只能通过未设置 MSG_OOB 可选项的普通输入函数读取。因为 TCP 不存在真正意义上的「外带数据」。实际上,MSG_OOB 中的 OOB 指的是 Out-of-band ,而「外带数据」的含义是:
通过完全不同的通信路径传输的数据。
即真正意义上的 Out-of-band 需要通过单独的通信路径高速传输数据,但是 TCP 不另外提供,只利用 TCP 的紧急模式(Urgent mode)进行传输。
紧急模式工作原理:
MSG_OOB 的真正意义在于督促数据接收对象尽快处理数据。这是紧急模式的全部内容,而 TCP 「保持传输顺序」的传输特性依然成立。下面是 MSG_OOB 可选项状态下的数据传输过程,如图:

上面是: send(sock, "890", strlen("890"), MSG_OOB);
图上是调用这个函数的缓冲状态。如果缓冲最左端的位置视作偏移量 0 。字符 0 保存于偏移量 2 的位置。另外,字符 0 右侧偏移量为 3 的位置存有紧急指针(Urgent Pointer)。紧急指针指向紧急消息的下一个位置(偏移量加一),同时向对方主机传递以下信息:
紧急指针指向的偏移量为 3 之前的部分就是紧急消息。
也就是说,实际上只用了一个字节表示紧急消息。这一点可以通过图中用于传输数据的 TCP 数据包(段)的结构看得更清楚,如图:

TCP 数据包实际包含更多信息。TCP 头部包含如下两种信息:
- URG=1:载有紧急消息的数据包
- URG指针:紧急指针位于偏移量为 3 的位置。
指定 MSG_OOB 选项的数据包本身就是紧急数据包,并通过紧急指针表示紧急消息所在的位置。紧急消息的意义在于督促消息处理,而非紧急传输形式受限的信息。
检查输入缓冲:
同时设置 MSG_PEEK 选项和 MSG_DONTWAIT 选项,以验证输入缓冲是否存在接收的数据。设置 MSG_PEEK 选项并调用 recv 函数时,即使读取了输入缓冲的数据也不会删除。因此,该选项通常与 MSG_DONTWAIT 合作,用于以非阻塞方式验证待读数据存在与否。下面的示例是二者的含义:
peek_recv:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>#define BUF_SIZE 30
void error_handling(char *message);int main(int argc, char *argv[])
{int acpt_sock, recv_sock;struct sockaddr_in acpt_adr, recv_adr;int str_len, state;socklen_t recv_adr_sz;char buf[BUF_SIZE];if (argc != 2){printf("Usage : %s <port>\n", argv[0]);exit(1);}acpt_sock = socket(PF_INET, SOCK_STREAM, 0);memset(&acpt_adr, 0, sizeof(acpt_adr));acpt_adr.sin_family = AF_INET;acpt_adr.sin_addr.s_addr = htonl(INADDR_ANY);acpt_adr.sin_port = htons(atoi(argv[1]));if (bind(acpt_sock, (struct sockaddr *)&acpt_adr, sizeof(acpt_adr)) == -1)error_handling("bind() error");listen(acpt_sock, 5);recv_adr_sz = sizeof(recv_adr);recv_sock = accept(acpt_sock, (struct sockaddr *)&recv_adr, &recv_adr_sz);while (1){//保证就算不存在待读取数据也不会阻塞str_len = recv(recv_sock, buf, sizeof(buf) - 1, MSG_PEEK | MSG_DONTWAIT);if (str_len > 0)break;}buf[str_len] = 0;printf("Buffering %d bytes : %s \n", str_len, buf);//再次调用 recv 函数,这一次没有设置任何可选项,所以可以直接从缓冲区读出str_len = recv(recv_sock, buf, sizeof(buf) - 1, 0);buf[str_len] = 0;printf("Read again: %s \n", buf);close(acpt_sock);close(recv_sock);return 0;
}void error_handling(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}
peek_send:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
void error_handling(char *message);int main(int argc, char *argv[])
{int sock;struct sockaddr_in send_adr;if (argc != 3){printf("Usage : %s <IP> <port>\n", argv[0]);exit(1);}sock = socket(PF_INET, SOCK_STREAM, 0);memset(&send_adr, 0, sizeof(send_adr));send_adr.sin_family = AF_INET;send_adr.sin_addr.s_addr = inet_addr(argv[1]);send_adr.sin_port = htons(atoi(argv[2]));if (connect(sock, (struct sockaddr *)&send_adr, sizeof(send_adr)) == -1)error_handling("connect() error");write(sock, "123", strlen("123"));close(sock);return 0;
}void error_handling(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}
运行结果:

当使用MSG_PEEK标志时,接收函数会将数据复制到指定的缓冲区中,但是这些数据仍然保留在套接字的接收缓冲区中。这意味着,即使再次调用接收函数,仍然可以读取相同的数据。这对于某些特定的应用场景可能是有用的。
可以通过结果验证,仅发送了一次的数据被读取了 2 次,因为第一次调用 recv 函数时设置了 MSG_PEEK 可选项。
13.2 readv & writev 函数
使用 readv & writev 函数:
readv & writev 函数的功能可概括如下:
对数据进行整合传输及发送的函数。
也就是说,通过 writev 函数可以将分散保存在多个缓冲中的数据一并发送,通过 readv 函数可以由多个缓冲分别接收。因此,适用这 2 个函数可以减少 I/O 函数的调用次数。下面先介绍 writev 函数:
#include <sys/uio.h>
ssize_t writev(int filedes, const struct iovec *iov, int iovcnt);
/*
成功时返回发送的字节数,失败时返回 -1
filedes: 表示数据传输对象的套接字文件描述符。但该函数并不仅限于套接字,因此,可以像 read 一样向向其传递文件或标准输出描述符.
iov: iovec 结构体数组的地址值,结构体 iovec 中包含待发送数据的位置和大小信息
iovcnt: 向第二个参数传递数组长度
*/
上述第二个参数中出现的数组 iovec 结构体的声明如下:
struct iovec
{void *iov_base; //缓冲地址size_t iov_len; //缓冲大小
};
下图是该函数的使用方法:

writev 的第一个参数,是文件描述符,因此向控制台输出数据,ptr 是存有待发送数据信息的 iovec 数组指针。第三个参数为 2,因此,从 ptr 指向的地址开始,共浏览 2 个 iovec 结构体变量,发送这些指针指向的缓冲数据。
下面是 writev 函数的使用示例:
#include <stdio.h>
#include <sys/uio.h>
int main(int argc, char *argv[])
{struct iovec vec[2];char buf1[] = "ABCDEFG";char buf2[] = "1234567";int str_len;vec[0].iov_base = buf1;vec[0].iov_len = 3;vec[1].iov_base = buf2;vec[1].iov_len = 4;str_len = writev(1, vec, 2);puts("");printf("Write bytes: %d \n", str_len);return 0;
}
运行结果:

下面介绍 readv 函数,功能和 writev 函数正好相反.函数为:
#include <sys/uio.h>
ssize_t readv(int filedes, const struct iovc *iov, int iovcnt);
/*
成功时返回接收的字节数,失败时返回 -1
filedes: 表示数据传输对象的套接字文件描述符。但该函数并不仅限于套接字,因此,可以像 write 一样向向其传递文件或标准输出描述符.
iov: iovec 结构体数组的地址值,结构体 iovec 中包含待数据保存的位置和大小信息
iovcnt: 第二个参数中数组的长度
*/
下面是示例代码:
#include <stdio.h>
#include <sys/uio.h>
#define BUF_SIZE 100int main(int argc, char *argv[])
{struct iovec vec[2];char buf1[BUF_SIZE] = {0,};char buf2[BUF_SIZE] = {0,};int str_len;vec[0].iov_base = buf1;vec[0].iov_len = 5;vec[1].iov_base = buf2;vec[1].iov_len = BUF_SIZE;str_len = readv(0, vec, 2);printf("Read bytes: %d \n", str_len);printf("First message: %s \n", buf1);printf("Second message: %s \n", buf2);return 0;
}
运行结果:
从图上可以看出,首先截取了长度为 5 的数据输出,然后再输出剩下的。
合理使用 readv & writev 函数:
实际上,能使用该函数的所有情况都适用。例如,需要传输的数据分别位于不同缓冲(数组)时,需要多次调用 write 函数。此时可通过 1 次 writev 函数调用替代操作,当然会提高效率。同样,需要将输入缓冲中的数据读入不同位置时,可以不必多次调用 read 函数,而是利用 1 次 readv 函数就能大大提高效率。
其意义在于减少数据包个数。假设为了提高效率在服务器端明确禁用了 Nagle 算法。其实 writev 函数在不采用 Nagle 算法时更有价值,如图:

上述示例中待发送的数据分别存在3个不同的地方,此时如果使用write函数则需要3次函数调用。.但若为提高速度而关闭了Nagle算法,则极有可能通过3个数据包传递数据。反之,若使用writev函数将所有数据一次性写入输出缓冲,则很有可能仅通过1个数据包传输数据。所以writev函数和readv函数非常有用。
习题:
1、利用 readv & writev 函数收发数据有何优点?分别从函数调用次数和 I/O 缓冲的角度给出说明。
需要传输的数据分别位于不同缓冲(数组)时,需要多次调用 write 函数。此时可通过 1 次 writev 函数调用替代操作,当然会提高效率。同样,需要将输入缓冲中的数据读入不同位置时,可以不必多次调用 read 函数,而是利用 1 次 readv 函数就能大大提高效率。
2、通过 recv 函数验证输入缓冲中是否存在数据时(确认后立即返回时),如何设置 recv 函数最后一个参数中的可选项?分别说明各可选项的含义。
使用 MSG_PEEK 来验证输入缓冲中是否存在待接收的数据。
相关文章:
《TCP IP网络编程》第十三章
第 13 章 多种 I/O 函数 13.1 send & recv 函数 Linux 中的 send & recv: send 函数定义: #include <sys/socket.h> ssize_t send(int sockfd, const void *buf, size_t nbytes, int flags); /* 成功时返回发送的字节数,失败…...
驱动开发 day8 (设备树驱动,按键中断实现led亮灭)
//编译驱动 (注意Makefile的编译到移植到开发板的内核) make archarm //清除编译生成文件 make clean ****************************************** //安装驱动 insmod mycdev.ko //卸载驱动 rmmod mycdev 需要在<内核路径>/arch/arm/boot/dts/ 修改 stm32mp157a-fsm…...
DataX将MySQL数据同步到HDFS中时,空值不处理可以吗
DataX将MySQL数据同步到HDFS中时,空值存到HDFS中时,默认是存储为\N,这样会有两个缺点: 会产生歧义,如果MySQL业务数据中有\N数据,那么存储到HDFS上是\N,null值存储也是\N,当用Hive查…...
P3373 【模板】线段树 2(乘法与加法)(内附封面)
【模板】线段树 2 题目描述 如题,已知一个数列,你需要进行下面三种操作: 将某区间每一个数乘上 x x x;将某区间每一个数加上 x x x;求出某区间每一个数的和。 输入格式 第一行包含三个整数 n , q , m n,q,m n,…...
实现langchain-ChatGLM API调用客户端(及未解决的问题)
langchain-ChatGLM是一个基于本地知识库的LLM对话库。其基于text2vec-large-Chinese为Embedding模型,ChatGLM-6B为对话大模型。原项目地址:https://github.com/chatchat-space/langchain-ChatGLM 对于如何本地部署ChatGLM模型,可以参考我之前…...
【AltWalker】模型驱动:轻松实现自动化测试用例的生成和组织执行
目录 模型驱动的自动化测试 优势 操作步骤 什么是AltWalker? 安装AltWalker 检查是否安装了正确的版本 牛刀小试 创建一个测试项目 运行测试 运行效果 在线模型编辑器 VScode扩展 本地部署 包含登录、选择产品、支付、退出登录的模型编写 模型效果 1…...
大数据课程E3——Flume的Sink
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 掌握Sink的HDFS Sink; ⚪ 掌握Sink的Logger Sink; ⚪ 掌握Sink的File Roll Sink; ⚪ 掌握Sink的Null Sink; ⚪ 掌握Sink的AVRO Sink; ⚪ 掌握Sink的Custom Sink; 一、HDFS Sink …...
如何快速做单元测试?
首先写unit test之前,要确认自己的测试遵循两个原则: 1、尽量不要干涉原来的代码。从阅读代码的体验来说,不要让你的测试(哪怕是一小段if..else...的代码)出现在你准备测试的代码中。 2、代码要只是测试某个class里面…...
不同对象的集合转换
https://blog.csdn.net/qq_42483473/article/details/128984514 import com.alibaba.fastjson.JSON;import java.util.ArrayList; import java.util.List;/*** author */ public class ObjectConversion {/*** 从List<A> copy到List<B>* param list List<B>…...
【机器学习】Gradient Descent
Gradient Descent for Linear Regression 1、梯度下降2、梯度下降算法的实现(1) 计算梯度(2) 梯度下降(3) 梯度下降的cost与迭代次数(4) 预测 3、绘图4、学习率 首先导入所需的库: import math, copy import numpy as np import matplotlib.pyplot as plt plt.styl…...
直播读弹幕机器人:直播弹幕采集+文字转语音(附完整代码)
目录 前言代码实现请求数据解析数据文字转语音完整代码 高级点的tk界面版 前言 直播读弹幕机器人是指能够实时读取直播平台上观众发送的弹幕,并将其转化为语音进行播放的机器人。这种机器人通常会使用文字转语音技术,将接收到的弹幕文本转为语音&#x…...
K3s vs K8s:轻量级对决 - 探索替代方案
在当今云原生应用的领域中,Kubernetes(简称K8s)已经成为了无可争议的领导者。然而,随着应用规模的不断增长,一些开发者和运维人员开始感受到了K8s的重量级特性所带来的挑战。为了解决这一问题,一个名为K3s的…...
dev控件gridControl,gridview中添加合计
需求:在合并结账查询中,双击每一条结账出现这次结账对应的结算明细: 弹出的页面包括:结算日期,ID,姓名,费别,预交金收入,结算金额,收据号,合计&a…...
SpringBoot基础认识
创建SpringBoot模块 首先需要引设置maven并引用maven环境 1.打开项目结构,new module,选择Spring Initializr,URL选默认: group填写分组如com.kdy , Artifact起个模块名如springboot_quickstart,Type选择M…...
二十三种设计模式第十九篇--命令模式
命令模式是一种行为设计模式,它将请求封装成一个独立的对象,从而允许您以参数化的方式将客户端代码与具体实现解耦。在命令模式中,命令对象充当调用者和接收者之间的中介。这使您能够根据需要将请求排队、记录请求日志、撤销操作等。 命令模…...
STM32基础入门学习笔记:基础知识和理论 开发环境建立
文件目录: 一:基础知识和理论 1.ARM简介 2.STM32简介 3.STM32命名规范 4.STM32内部功能* 5.STM32接口定义 二:开发环境建立 1.开发板简介 2.ISP程序下载 3.最小系统电路 4.KEIL的安装 5.工程简介与调试流程 6.固件库的安装 7.编…...
Qt应用开发(基础篇)——数值微调输入框QAbstractSpinBox、QSpinBox、QDoubleSpinBox
目录 一、前言 二、QAbstractSpinBox类 1、accelerated 2、acceptableInput 3、alignment 4、buttonSymbols 5、correctionMode 6、frame 7、keyboardTracking 8、readOnly 9、showGroupSeparator 10、specialValueText 11、text 12、wrapping 13、信号 二、Q…...
html | 无js二级菜单
1. 效果图 2. 代码 <meta charset"utf-8"><style> .hiddentitle{display:none;}nav ul{list-style-type: none;background-color: #001f3f;overflow:hidden; /* 父标签加这个,防止有浮动子元素时,该标签失去高度*/margin: 0;padd…...
appium的基本使用
appium的基本使用 一、appium的基本使用appium环境安装1、安装Android SDK 2、安装Appium3、安装手机模拟器4、Pycharm安装 appium-python-alicent5、连接appium和模拟器6、Python代码调用appium软件,appium软件在通过adb命令调用android操作系统(模拟器…...
Dockerfile构建nginx镜像(编译安装)
Dockerfile构建nginx镜像 1、建立工作目录 [rootdocker ~]# mkdir nginx [rootdocker ~]# cd nginx/ 2、编写Dockerfile文件 [rootdocker nginx]# vim run.sh [rootdocker nginx]# vim Dockerfile #基于的基础镜像 FROM centos:7#镜像作者信息 MAINTAINER Crushlinux <…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
