【Linux网络】认识协议(TCP/UDP)、Mac/IP地址和端口号、网络字节序、socket套接字

目录
- 1、初识协议
- 2、UDP、TCP
- 3、Mac、IP地址
- 4、端口号
- 5、网络字节序
- 6、socket
1、初识协议
- 协议就是一种约定。
- 如何让不同厂商生产的计算机之间能够互相通信?需要由权威组织或公司制定网络协议。
- 协议本质也是软件,在设计上为了更好的进行模块化,解耦合,因此被设计为层状结构。
协议本质也是软件,为了更好的模块换,降低耦合度,所以被设计为层状结构。在Linux网络协议栈中,各个层次协同工作,以实现数据的封装、传输、路由和接收。从底层到高层,这些层次包括:
-
链路层(数据链路层):负责物理网络上的数据传输,包括帧的封装、错误检测和纠正等。在Linux中,这一层通常与特定的网络接口卡(NIC)驱动程序相关联。
-
网络层:提供IP地址管理和路由功能,确保数据包能够正确地从一个网络传输到另一个网络。Linux支持IPv4和IPv6两种IP协议版本。
-
传输层:提供端到端的通信服务,确保数据的可靠传输或快速、不可靠的传输。TCP(传输控制协议)提供可靠的数据传输,而UDP(用户数据报协议)则提供无连接的数据传输服务。
-
应用层:提供用户和网络服务之间的接口,包括HTTP(用于Web浏览)、SMTP(用于电子邮件发送)、FTP(用于文件传输)等多种应用层协议。
一般而言:
- 对于一台主机,它的操作系统内核实现了从传输层到物理层的内容
- 对于一台路由器,它实现了从网络层到物理层
- 对于一台交换机,它实现了从数据层到物理层
- 对于一台集线器,它只实现了物理层
2、UDP、TCP
传输层的典型代表:
TCP协议 | UDP协议 |
---|---|
传输层协议 | 传输层协议 |
有连接 | 无连接 |
可靠传输 | 不可靠传输 |
面向字节流 | 面向数据报 |
TCP协议格式:
- 确认应答至少应该是一个完整的TCP报头
- 确认序号 = 序号 + 1,表示该序号之前的内容被全部收到了
- 为什么要有序号和确认序号两个序号,并且是独立的字段?
TCP报文,大多数情况下既是应答,又是数据,即捎带应答机制,这个时候序号和确认序号这两个字段要被同时使用。
TCP 将每个字节的数据都进行了编号,即为序列号。每一个 ACK 都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据,下一次你从哪里开始发。
- 4位首部长度:这个字段的单位是4字节,取值范围是0到15,乘以4后得到报头的实际字节长度范围是20到60字节。当首部长度为5时,表示的是标准的20字节报头。
6 位标志位:用于区分报文类型
标志位 | 说明 |
---|---|
URG | 紧急指针是否有效,需要优先处理的报文 |
ACK | 表明自己是应答报文 |
PSH | 提示接收端应用程序立刻从 TCP 缓冲区把数据读走 |
RST | 对方要求重新建立连接,我们把携带 RST 标识的称为复位报文段 |
SYN | 请求建立连接,我们把携带 SYN 标识的称为同步报文段 |
FIN | 通知对方,本端要关闭了,我们称携带 FIN 标识的为结束报文段 |
- 16位窗口大小:流量控制,由接收缓冲区剩余空间大小决定,由滑动窗口实现
- 超时重传:在TCP连接中,当发送方发送一个数据段后,会启动一个超时计时器,如果在计时器超时之前,发送方没有收到接收方的确认(ACK)报文,那么发送方就会认为该数据段已经丢失,并重新发送该数据段,直到收到确认报文或达到重传次数限制为止。
在正常情况下,TCP 要经过三次握手建立连接,四次挥手断开连接。
为什么要三次握手?四次挥手?
- 建立双方主机通信的意愿共
- 双方验证全双工信道的通畅性
- 本质是四次握手,因为捎带应答机制变为三次握手
- Tcp是全双工的,要关闭两个朝向上的连接
我们测试时有时会出现bind error,是什么原因?
- TCP 协议规定,主动关闭连接的一方要处于
TIME_ WAIT
状态,等待两个MSL(一般为2分钟)的时间后才能回到 CLOSED 状态 - 我们使用 Ctrl-C 终止了 server,所以 server 是主动关闭连接的一方,在
TIME_WAIT
期间仍然不能再次监听同样的 server 端口
如何解决?
- 使用
setsockopt()
设置 socket 描述符的选项SO_REUSEADDR
为 1,表示允许创建端口号相同但 IP 地址不同的多个 socket 描述符
int opt = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
CLOSE_WAIT
状态则是被动关闭连接的一方在接收到FIN报文并发送ACK后的状态- 如果服务器不关闭sockfd,则只会完成两次挥手,服务器就会长时间处于
close_wait
状态。
滑动窗口:
- 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值
- 操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答,只有确认应答过的数据,才能从缓冲区删掉
- 窗口只能向右滑动,且根据对方接收缓冲区的大小调整大小
丢包重传问题:
- 如果发送端主机连续三次收到了同样一个 “1001” 这样的应答,则说明我们只收到了 “1001” 之前的报文,在这种情况下,发送方不等待超时定时器的触发,而是立即重传该丢失的数据包,即将对应的数据 1001 - 2000 重新发送。这种机制被称为 "高速重发控制”(快重传)
拥塞控制:
- 虽然 TCP 滑动窗口能够高效可靠的发送大量的数据,但是如果刚开始就发送大量的数据,仍然可能引发问题。因为网络上有很多的计算机,可能当前的网络状态就已经比较拥堵,在不清楚当前网络状态下,贸然发送大量的数据,很有可能雪上加霜。
- TCP引入慢启动机制,即先发少量的数据探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据
- 当拥塞窗口达到慢启动阈值后,TCP会进入拥塞避免阶段。此时,拥塞窗口会按线性速率增长,以避免突然的大幅增加导致网络拥塞
Tcp通过校验和、序列号(按序到达、去重)、确认应答、超时重发、连接管理、流量控制、拥塞控制等保证可靠性;通过滑动窗口、快速重传、延迟应答、捎带应答等提高性能。
UDP协议格式:
-
无连接:知道对端的 IP 和端口号就直接进行传输,不需要建立连接;
-
不可靠:没有确认机制,没有重传机制,如果因为网络故障该段无法发到对方,UDP 协议层也不会给应用层返回任何错误信息;
-
面向数据报:不能够灵活的控制读写数据的次数和数量;
-
16 位 UDP 长度,表示整个数据报(UDP 首部+UDP 数据)的最大长度,如果要传输的数据超过 64K,就需要在应用层手动的分包,多次发送,并在接收端手动拼装;
-
如果校验和出错,就会直接丢弃;
-
UDP协议的报头是固定的8字节,所以协议的接收方直接截取前8个字节的报头,剩下的就是有效数据。
UDP的缓冲区:
- 发送缓冲区:UDP 没有真正意义上的发送缓冲区,调用 sendto 会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作;
- 接收缓冲区:UDP的接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致,如果缓冲区满了,再到达的 UDP 数据就会被丢弃;
TCP/UDP 对比:
- 无论是Tcp有连接Udp无连接,还是Tcp可靠Udp不可靠,这都是它们的特性,不是优缺点,它们适用于不同的需求场景
- TCP 用于可靠传输的情况,应用于文件传输,重要状态更新等场景
- UDP 用于对高速传输和实时性要求较高的通信领域,例如早期的 QQ、视频传输、广播等
3、Mac、IP地址
每台主机在局域网上,要有唯一的标识来保证主机的唯一性:mac 地址。
以太网中,任何时刻,只允许一台机器向网络中发送数据。如果有多台同时发送,会发生数据干扰,我们称之为数据碰撞,所有发送数据的主机要进行碰撞检测和碰撞避免,没有交换机的情况下,一个以太网就是一个碰撞域,局域网通信的过程中,主机对收到的报文确认是否是发给自己的,是通过目标mac地址判定的。
其中每层都有协议,当我们进行传输流程的时候,要进行封装和解包:
Tcp/IP通讯过程:
IP 地址是在 IP 协议中, 用来标识网络中不同主机的地址,对于 IPv4 来说, IP 地址是一个 4 字节,32 位的整数,我们通常也使用 “点分十进制” 的字符串表示 IP 地址, 例如1.94.9.200,用点分割的每一个数字表示一个字节,范围是 0 - 255。
Mac地址 vs IP地址:
唐僧从东土大唐出发,要去西天拜佛求经,途中要经过女儿国和黑风岭,女儿国和黑风岭是相邻两地。
- 东土大唐 -> 西天:源IP地址 -> 目的IP地址
- 女儿国 -> 黑风岭:源Mac地址 -> 目的Mac地址
其中经过的各个国家就是路由器,相邻的国家在同一个局域网中,路由器路由的下一个目的地是根据目的IP地址路由的,局域网通信需要Mac地址指路,一般Mac地址只在局域网中有效,IP地址几乎不变。
IP在网络中标识主机的唯一性,数据传输到主机不是目的而是手段,最终到达主机内的目的进程才是目的。但是在主机中,同一时间进程可能有很多,那怎么找到目的进程呢?
4、端口号
端口号(port)是传输层协议的内容,是一个2字节16位的整数,端口号标识唯一进程,一个端口号只能被一个进程占用。
IP地址+端口号能够标识网络中的唯一进程。
网络通信,本质上也是进程间通信。
其中 0 - 1023 是知名端口号,HTTP, FTP, SSH等这些广为使用的应用层协议,它们的端口号都是固定的。1024 - 65535 是操作系统动态分配的端口号,比如客户端程序的端口号就是有操作系统动态分配的。
pid也可以标识唯一进程,为什么还要引入端口号呢?
进程pid属于系统概念,如果继续沿用pid标识唯一进程,会增加耦合度。另外,一个进程可以绑定多个端口号,但一个端口号不能被多个进程绑定。
网络通信的本质,也是进程间通信,本质是两个互联网进程代表人来进行通信。IP + port 叫做套接字socket。
一个进程可以 bind 多个端口号,但一个端口号不能被多个进程 bind。
5、网络字节序
内存中的多字节数据相对于内存地址有大端和小端之分,网络数据流同样有大端小端之分,如何定义网络数据流的地址?
- 网络数据流的地址被规定:先发出去的是低地址,后发出去的是高地址。
- TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。
为使网络程序具有可移植性,使用样的C代码在大端和小端机器上编译后都能正常运行,可以调用下面库函数做网络字节序和主机字节序的转换。
#include <arpa/inet.h>uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t hostlong);
uint16_t ntohs(uint16_t hostshort);
h
表示host
,n
表示network
,l
表示32位长整数,s
表示16位短整数。
6、socket
socket常见API:
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address,socklen_t address_len);// 开始监听 socket (TCP, 服务器)
int listen(int socket, int backlog);// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address,socklen_t* address_len);// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
socket:
socket()
打开一个网络通讯端口,如果成功,就像open()一样返回一个文件描述符,出错返回-1- 应用程序可以像读写文件一样用 read/write 在网络上收发数据
- 对于 IPv4,
family
参数指定为AF_INET
- 对于 TCP 协议,
type
参数指定为SOCK_STREAM
,表示面向流的传输协议protocol
参数指定为 0 即可
bind:
- bind()成功返回 0,失败返回-1
- bind()的作用是将参数 sockfd 和 myaddr 绑定在一起,使 sockfd 这个用于网络通讯的文件描述符监听 myaddr 所描述的地址和端口号
- struct sockaddr *是一个通用指针类型,myaddr 参数实际上可以接受多种协议的 sockaddr 结构体,而它们的长度各不相同,所以需要第三个参数 addrlen指定结构体的长度,我们可以对 myaddr 参数这样初始化:
struct sockaddr_in local; memset(&local, 0, sizeof(local)); local.sin_family = AF_INET; local.sin_port = htons(_port); local.sin_addr.s_addr = INADDR_ANY;
listen:
- listen()声明 sockfd 处于监听状态,并且最多允许有 backlog 个客户端处于连接
等待状态,如果接收到更多的连接请求就忽略- listen()成功返回 0,失败返回-1
accept:
- 三次握手完成后,服务器调用 accept()接受连接
- 如果服务器调用 accept()时还没有客户端的连接请求,就阻塞等待,直到有客户端
连接上来- addr 是一个传出参数,accept()返回时传出客户端的地址和端口号
- 如果给 addr 参数传 NULL,表示不关心客户端的地址
- addrlen 参数是一个传入传出参数(value-result argument),传入的是调用者提供的,缓冲区 addr 的长度以避免缓冲区溢出问题,传出的是客户端地址结构体的实际长度
connect:
- 客户端需要调用 connect()连接服务器
- connect 和 bind 的参数形式一致,区别在于 bind 的参数是自己的地址,connect 的参数是对方的地址
- connect()成功返回 0,出错返回-1
注意:
- 由于客户端不需要固定的端口号,因此不必调用 bind(),客户端的端口号由内核自动分配
- 客户端不是不允许调用 bind(),只是没有必要显示的调用 bind()固定一个端口号,否则如果在同一台机器上启动多个客户端,就会出现端口号被占用导致不能正确建立连接
- 服务器也不是必须调用 bind(),但如果服务器不调用 bind(),内核会自动给服务器分配监听端口,每次启动服务器时端口号都不一样,客户端要连接服务器就会遇到麻烦
sockaddr结构:
sock API是一层抽象的网络编程接口,适用于各种底层网络协议,各种网络协议的地址格式并不相同。
socket API 可以都用struct sockaddr*
类型表示,在使用的时候需要强制转换成sockaddr_in
,增加了程序的通用性。
本篇文章的分享就到这里了,如果您觉得在本文有所收获,还请留下您的三连支持哦~

相关文章:

【Linux网络】认识协议(TCP/UDP)、Mac/IP地址和端口号、网络字节序、socket套接字
⭐️个人主页:小羊 ⭐️所属专栏:Linux 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 1、初识协议2、UDP、TCP3、Mac、IP地址4、端口号5、网络字节序6、socket 1、初识协议 协议就是一种约定。如何让不同厂商生产的计…...

12、数据库、Sql单表多表
文章目录 一、数据库简介二、单表三、多表四、等值连接五、内联结六、inner join on、left join on、right join on区别七、模糊查找八、作业 一、数据库简介 数据在内存: 优点:读写速度快缺点:程序结束后数据丢失 保存到文件 优点&#…...
Spring Boot 实现图片上传并生成缩略图功能
在实际开发中,上传图片并生成缩略图是一项常见需求,例如在电商平台、社交应用等场景中,缩略图可以有效提高页面加载速度,优化用户体验。本文将介绍如何在 Spring Boot 项目中实现上传图片并生成缩略图的功能。 📦 1. …...

洛谷B3664[语言月赛202209] 零食售卖点
B3664 [语言月赛202209] 零食售卖点 - 洛谷 代码区: #include<bits/stdc.h>using namespace std;int main(){int n;cin >> n;int arry[n],dp[n];for(int i0;i<n;i){cin >> arry[i];}dp[0]0;sort(arry,arryn);for(int i1;i<n;i){dp[i]arry…...
贪心算法:JAVA从理论到实践的探索
在计算机科学领域,贪心算法是一种简单而高效的算法设计策略,广泛应用于优化问题的求解。它通过在每一步选择中都采取当前状态下最优的选择,以期望最终得到全局最优解。本文将深入探讨贪心算法的原理、应用场景,并通过具体代码示例,帮助读者更好地理解和掌握这一算法。 一…...
线程池10种常见坑
1. 直接使用 Executors 创建线程池 直接使用 Executors 提供的快捷方法: ExecutorService executor Executors.newFixedThreadPool(10);问题 无界队列:newFixedThreadPool 使用的队列是 LinkedBlockingQueue,它是无界队列,任务…...

鸿蒙ArkTs如何实现pdf预览功能?
鸿蒙ArkTs如何实现pdf预览功能? 前言PDFKit运行示例代码报错真机运行先看效果一、预览本地pdf文件二、预览线上的pdf文件三、预览沙箱目录中pdf的文件(重点)效果中的整体代码总结 Harmony OS NEXT版本(接口及解决方案兼容API12版本或以上版本) 前言 在开…...

KylinSP3 | 防火墙和麒麟安全增强设置KySec
一、系统防火墙原理 麒麟操作系统从V10版本开始,默认使用了Firewalld防火墙,Firewalld是能提供动态管理的防火墙,支持网络/防火墙区域,用于定义网络连接或接口的信任级别。支持IPv4和IPv6防火墙设置、以太网桥接和IP集。将运行时…...
【C++】面试常问八股
5、内存管理 野指针 野指针指的是未进行初始化或未清零的指针,不是NULL指针野指针产生原因及解决方案: 指针变量未初始化:指针变量定义时若未初始化,则其指向的地址是随机的,不为NULL;定义时初始化为NULL…...

vscode多文件编译构建(CMake)和调试C++
目录 1. CMake 基础构建工具及作用相关配置文件 2. 配置 tasks.json关键字段详细解释 3. 配置 launch.json关键字段详细解释 4. 配置 CMakeLists.txt关键部分详细解释 5. 构建和调试项目1. 仅构建项目1.1 任务执行顺序1.2 cmake 任务执行详情1.3 build 任务执行详情1.4 构建后的…...
使用Docker 部署 LNMP+Redis 环境
使用Docker 部署 LNMPRedis 环境 Docker 简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互…...
文件上传漏洞学习笔记
一、漏洞概述 定义 文件上传漏洞指未对用户上传的文件进行充分安全校验,导致攻击者可上传恶意文件(如Webshell、木马),进而控制服务器或执行任意代码。 危害等级 ⚠️ 高危漏洞(通常CVSS评分7.0)ÿ…...
375_C++_cloud手机推送,添加人脸告警信息到任务队列中,UploadAlarmPush是典型的工厂模式应用,为什么使用工厂模式完成这部分代码
一:AlarmFaceInfo的应用 让我帮你解析这个lambda表达式的实现: // ...................... .h ...........................// struct RsMsgPushTask_S : public Task{AlarmType_E mainAlarmType;unsigned int subAlarmType;DateTime alarmTime...
Spring Boot 中的日志管理
一、日志框架选择 1. 主流框架对比 框架特点Spring Boot 默认支持Logback- 性能优异,Spring Boot 默认集成- 支持自动热更新配置文件✅ (默认)Log4j2- 异步日志性能更强- 支持插件扩展- 防范漏洞能力更好❌ (需手动配置)JUL (JDK自带)- 无需额外依赖- 功能简单&am…...

火绒终端安全管理系统V2.0网络防御功能介绍
火绒终端安全管理系统V2.0 【火绒企业版V2.0】网络防御功能包含网络入侵拦截、横向渗透防护、对外攻击检测、僵尸网络防护、Web服务保护、暴破攻击防护、远程登录防护、恶意网址拦截。火绒企业版V2.0的网络防御功能,多层次、多方位,守护用户终端安全。 …...

海康摄像头 + M7s(Monibuca) + FFmpeg + Python实现多个网络摄像头视频流推流
最近在研究流媒体服务器时,我注意到了一款开源软件——M7s。按照官网的指南部署完成后,我开始进行测试,发现单视频流推送非常顺利,没有任何问题。然而,当我尝试进行多视频流推送时,却发现网上的相关教程寥寥…...
抖音视频如何下载保存去水印
随着短视频平台的兴起,抖音作为国内最受欢迎的短视频平台之一,吸引了大量用户上传和观看各种创意视频。许多用户在浏览抖音视频时,往往会想要保存一些有趣或精彩的视频片段,但抖音视频通常会有水印,影响观看体验。为了…...

【鸿蒙开发】第三十九章 LazyForEach:数据懒加载
目录 1 背景 2 使用限制 键值生成规则 组件创建规则 首次渲染 非首次渲染 改变数据子属性 使用状态管理V2 拖拽排序 1 背景 LazyForEach从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。当在滚动容器中使用了LazyForEach,框架…...

HTTP-
一.HTTP 1.什么是HTTP HTTP(超文本传输协议)是一种工作在应用层的协议.主要用于网站,就是浏览器和服务器之间的数据传输. 小知识:什么是超文本传输协议 文本:是字符串.(能在utf8/gbk码表上找到合法字符) 超文本:不仅可以传输字符串,也可以传输图片,html等 富文本:word文档 2.HT…...
创建型模式 - 原型模式 (Prototype Pattern)
创建型模式 -原型模式 (Prototype Pattern) 它允许通过复制现有对象来创建新对象,而无需知道对象的具体创建细节。在 Java 中,可以通过实现 Cloneable 接口和重写 clone() 方法来实现原型模式。 有深、浅两种克隆 类实现 Cloneable 接口就可以深克隆如果…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...