IP/TCP/UDP协议的关键知识点

导语:网络协议是理解网络情况的基础,当遇到网络问题时,首先可以从网络协议入手,熟悉的网络协议可以有效帮助小伙伴们排查或者说定位大概的问题方面。本文整理了目前最常用的网络通信协议,相信对小伙伴们肯定都有帮助。

1. 以太帧

1.1. 帧格式

  • 还有其他的格式帧,但用的比较少;
  • 所有的网络设备都需要支持以太帧格式;
  • 目的地址、源地址都是指的MAC地址;
  • 可能存在分片的情况,在实际中还是可能会存在一些设备(尤其是旧设备)不能支持MTU为1500的情况;

1.2. MTU

MTU即Max Transfer Unit,最大传输单元,那么为什么MTU是1500呢?

以太网帧是传输中的最小可识别单元,再往下就是0101所对应的光信号,所以一条带宽同时只能发送一个以太网帧。如果同时发送多个,那么对端就无法重组成一个以太网帧。

1.2.1. 设置过大

假设MTU设置为65535,在100Mbps的带宽中(假设中间没有损耗),我们计算一下发送这一帧需要的时间:

( 65553 * 8 ) / ( 100 * 1024 * 1024 ) ≈ 0.005(s)

65553 = 65535 + 14 + 4

在100M网络下传输一帧就需要5ms,也就是说这5ms其他进程发送不了任何数据,如果是早先的电话拨号,网速只有2M的情况下:

( 65553 * 8 ) / ( 2 * 1024 * 1024 ) ≈ 0.100(s)

100ms内无法发送其他数据,简直不能接受。

1.2.2. 设置过小

假设MTU值设置为100,那么单个帧传输的时间,在2Mbps带宽下需要:

( 100 * 8 ) / ( 2 * 1024 * 1024 ) * 1000 ≈ 5(ms)

时间上已经能接受了,问题在于,不管MTU设置为多少,以太网头帧尾大小是固定的,都是14 + 4,所以在MTU为100的时候,一个以太网帧的传输效率为:

( 100 - 14 - 4 ) / 100 = 82%

写成公式就是:( T - 14 - 4 ) / T,当T趋于无穷大的时候,效率接近100%,也就是MTU的值越大,传输效率最高,但是基于上一点传输时间的问题,来个折中的选择,既然头加尾是18,那就凑个整来个1500,总大小就是1518,传输效率:

1500 / 1518 =  98.8%

100Mbps传输时间:

( 1518 * 8 ) / ( 100 * 1024 * 1024 ) * 1000 = 0.11(ms)

2Mbps传输时间:

( 1518 * 8 ) / ( 2 * 1024 * 1024 ) * 1000 = 5.79(ms)

总体上时间都还能接受。

2. RFC

RFC:Request For Comments(RFC),是一系列以编号排定的文件,基本的互联网通信协议都有在RFC文件内详细说明。

https://www.rfc-editor.org/rfc

国内的一个镜像(看名字是南京大学的):http://mirrors.nju.edu.cn/rfc/inline-errata/ 里面有各种协议的文档。

协议编号说明
IP791
IPV62460
TCP793
UDP768
ICMP777、792
DNS1035
FTP959
SNMP1067、1098、1157
HTTP1.01945
HTTP1.12616、2617
NAT1631rfc3022淘汰了rfc1631

3. IP报文

http://mirrors.nju.edu.cn/rfc/inline-errata/rfc791.html

0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1...+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|Version|  IHL  |Type of Service|          Total Length         |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|         Identification        |Flags|      Fragment Offset    |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|  Time to Live |    Protocol   |         Header Checksum       |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                       Source Address                          |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                    Destination Address                        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                    Options                    |    Padding    |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Example Internet Datagram Header
  • Version:版本,4表示IPv4,6表示IPv6;
  • IHL:报文首部长度;
  • Type Of Service:服务类型,用于指示服务质量;
  • Total Length:总长度,含报文首部和数据部分;
  • Identification:标识,发送方分配,用于标识数据包,具有相同标识字段的分片报文会被接收方重组成一个完整的数据包;
  • Flags:标志,3bit,bit0为预留,bit1(DF,Don't Fragment)0=可能分片,1=不分片,bit2(MF,More Fragment)0=最后的分片,1=会有更多的分片;
  • Fragment Offset:片偏移,13bit,表示该IP包在分片前的原始IP包中的位置,单位是8字节;
  • Time to Live:TTL,生存时间,每经过一个网络设备,这个值-1,如果到0,则该报文丢弃(需要重新计算校验和);
  • Protocol:协议,即数据部分的协议,例如:TCP、UDP等;
  • Header Checksum:头部校验和;
  • Source Address:源地址;
  • Destination Address:目的地址;
  • Options:可选字段,长度可变,例如有的命令会在每个报文中加入经过的IP;
  • Padding:填充,需要4字节对齐;

除可选字段外,IP头总长度为20字节。

4. TCP报文格式

http://mirrors.nju.edu.cn/rfc/inline-errata/rfc793.html

4.1. 分层关系

 +------+ +-----+ +-----+       +-----+|Telnet| | FTP | |Voice|  ...  |     |  Application Level+------+ +-----+ +-----+       +-----+|   |         |             |+-----+     +-----+       +-----+| TCP |     | RTP |  ...  |     |  Host Level+-----+     +-----+       +-----+|           |             |+-------------------------------+|    Internet Protocol & ICMP   |  Gateway Level+-------------------------------+|+---------------------------+|   Local Network Protocol  |    Network Level+---------------------------+Protocol Relationships

4.2. 格式

0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1...+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|          Source Port          |       Destination Port        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                        Sequence Number                        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                    Acknowledgment Number                      |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|  Data |           |U|A|P|R|S|F|                               || Offset| Reserved  |R|C|S|S|Y|I|            Window             ||       |           |G|K|H|T|N|N|                               |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|           Checksum            |         Urgent Pointer        |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                    Options                    |    Padding    |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                             data                              |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+TCP Header Format
  • Source Port:源端口,2字节,这就是为什么TCP协议中端口最多有65535个;
  • Destination Port:目的端口;
  • Sequence Number:序号,TCP中传输的数据流中每个字节都会有一个编号,序号字段的值指的是本报文段所发送的数据的第一个字节所在整个数据流的编号;
  • Acknowledgment Number:确认号,表示期望收到对方的下一个报文段的数据的第1个字节的序号,也可以描述为上次已经成功接收到的数据字节序号+1,只有ACK标识为1,该值才有效;
  • Data Offset:数据开始的位置,这里的数据指的是data,就是要发送的具体内容,需要注意的是,TCP报文也是4字节对齐的,也就是data一定是4字节的倍数开始;
  • Reserved:预留;
  • URG:紧急指针标志,1表示紧急指针有效;
  • ACK:ACK标志,1表示确认号有效,0表示报文中不含有确认信息,忽略确认号字段;
  • PSH:PUSH标志,1表示带有push标志的数据,指示接收方收到该数据后,需要尽快将报文交给应用程序;
  • RST:重建连接标志,1表示TCP连接中出现严重错误,例如程序挂了,则会由内核TCP协议栈发送RST报文至对端,表示必须要释放连接,后续根据情况重建;
  • SYN:同步序号标识,用来发起一个连接,1表示是syn报文;
  • FIN:finish标识,用于释放连接,1表示发送方已经没有数据发送了,可以关闭本方连接;
  • Window:滑动窗口大小,描述的是本方的拥塞情况;
  • Checksum:校验和;
  • Urgent Pointer:紧急指针,在URG为1时有效,具体不是很清楚做什么;
  • Options:可选字段;
  • Padding:填充;
  • data:具体数据;

TCP报文头最少占用20个字节。

4.3. Options

4.3.1. MSS

MSS即Max Segment Size,它指明本段可以接受的最大TCP分段的长度(Payload,不含TCP Header),也就是说,对端发送的每个分段的长度都不应该大于MSS(单位Byte)。

MSS占用两个字节,所以其最大值可以为65535。

一般而言:MSS = MTU(1500) - IP Header(20) - TCP Header(20) = 1460;

这个值是在三次握手时明确的,并且必须发送至对端,且只会在握手时发送。

它的格式:

        +--------+--------+---------+--------+|00000010|00000100|   max seg size   |+--------+--------+---------+--------+Kind=2   Length=4

因为是Option,所以允许服务器不发送给值,假设不发送的话,对端会将该值设置为:536Bytes。

4.3.2. Window Scale

Window Size的乘数因子,为了放大滑动窗口计算使用。

这个值是在三次握手时明确的,并且必须发送至对端,且只会在握手时发送。

它的格式:

        +--------+--------+---------+--------+|00000011|00000011|   shift count   |+--------+--------+---------+--------+Kind=3   Length=3

shift count是2的n次方中的n,例如7表示要放大128倍。

5. TCP三次握手

5.1. 三次握手过程

TCP协议中的 SYNSynchronize 的缩写。它是 TCP 三次握手过程中的首个报文,用于在建立连接时同步序列号。具体来说,SYN 报文允许发送方告诉接收方自己希望建立连接,并同时携带自己的初始序列号。

ACKAcknowledgment 的缩写,表示确认应答。在 TCP 协议中,ACK 用于确认已接收到的数据。具体来说,TCP 使用 ACK 报文来通知另一方数据包已经成功到达,从而确保数据传输的可靠性。

客户端状态变化:

  • 发送syn报文后,变为SYN_SENT状态;
  • 接收到SYN+ACK报文后,变为ESTABLISHED状态;

服务端状态变化:

  • 默认是LISTEN状态,此时是节点启动监听后的状态;
  • 收到客户端发送的SYN报文后,会变为SYN_RCVD状态;
  • 收到客户端的ACK报文后,变为ESTABLISHED状态;

5.2. 丢包咋办

5.2.1. 客户端SYN包丢失

Client发现自己没有收到ACK,会周期性重传SYN包,直到收到Server段的SYN+ACK。

5.2.2. 服务端回复的SYN+ACK丢失

Server发现自己没有收到ACK,会周期性重传SYN+ACK包,直到收到Client的ACK。

5.2.3. 客户端回复的ACK丢失

此时,对于Client而言,其已经变为了ESTABLISHED状态,但Sever端目前并不是ESTABLISHED状态,而是在一个中间等待状态(ACTIVE状态)。会存在下面这三种情况:

  • 假设两端都没有发送数据,那么Server会周期性重传SYN+ACK包,直到收到Client的确认;
  • 假设此时Client开始发送数据,Server收到了Client的数据包(包中也会有ACK),那么就会切换到ESTABLISHED状态,正常处理;
  • 假设Server需要发送数据,但明显此时无法发送,则会一直周期性的重传SYN+ACK,直到搜到Client的确认报文;

5.3. 连接队列

5.3.1. 什么是连接队列

连接队列,包括syns queue和accept queue两个,前者也被称为半连接队列,后者被称为全连接队列。其都是相对于服务端而言的,它们在三次握手的过程中如下:

5.3.2. 连接队列大小

syns queue的大小 = max(64, /proc/sys/net/ipv4/tcp_max_syn_backlog)

accept queue的大小 = min(backlog, /proc/sys/net/core/somaxconn),其中backlog是用户编程时在listen函数中设置的值。

5.3.3. backlog

backlog核心是内核给用户侧提供的允许连接的控制。

对于服务端(其实客户端也存在)有两个队列,Send-Q和Recv-Q,它们的关系如下:

  • Send-Q:其实就是accept queue的最大值,为min(backlog, /proc/sys/net/core/somaxconn);
  • Recv-Q:指的是已经建立成功连接(ESTABLISHED状态),但还没有交付给应用的TCP连接的数量,最大值为Send-Q + 1,可以认为允许有一个连接从accept queue中取出,但还没有交由应用,处于游离状态;

5.3.4. syns queue满

处理很暴力,所有新的SYN报文都会被丢弃,直到有空位。

5.3.5. accept queue满

有两种处理方式,可以通过修改/proc/sys/net/ipv4/tcp_abort_on_overflow来配置,其有效值有两个:0或者1,具体含义如下

  • 0:将该链接状态还原为SYN_RCVD状态,造成最后的ACK报文缺失的假象,等待客户端重发,然后再次尝试,这是一种修复/重试机制;
  • 1:直接发送RST报文给客户端,表示终止此连接,从syns queue中移除,此时客户端会收到104 connection reset by peer错误。

有的时候,可以刻意将值改为1,通过接收到的报文来判断是否是accept queue溢出导致的。

6. TCP四次挥手

6.1. 四次挥手过程

6.2. 为什么要2MSL?

MSL被认为是一个发送的时间,那么2MSL就被认为是一个发送和回复所需的最大时间,如果直到2MSL,Client仍然没有再次FIN,那么Client推断ACK已经成功被Server端接收,则结束TCP连接。

如果Client的ACK在回复过程中丢失的话,理论上Server端需要重新发送FIN报文,以便于正常结束连接。

6.3. MSL配置

位置:/proc/sys/net/ipv4/tcp_fin_timeout,单位是秒,这个值是2MSL的时间,假设是60,则一个MSL就是30s。

可以通过调整该值使得一个连接更快结束。

6.4. 大面积TIME-WAIT

WEB服务器比较容易会出现这种场景,例如有很多HTTP请求,对于Server端而言,会主动去释放这些连接,作为主动释放方,需要等到2MSL才能真正的释放,但处于CLOSE之前都会被视为占用了FD,那么就可能出现open too many files的问题。

这种情况一般的解决办法就是改一些内核配置:

#表示当keepalive启用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为300秒
net.ipv4.tcp_keepalive_time=1200
#表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数
net.ipv4.tcp_max_syn_backlog = 4096
#表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭
net.ipv4.tcp_syncookies = 1
#表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭
net.ipv4.tcp_tw_reuse = 1
#表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
net.ipv4.tcp_tw_recycle = 1
#减少超时前的探测次数
net.ipv4.tcp_keepalive_probes=5

也可以借鉴6.3章节,配置MSL时间。

6.5. 大面积CLOSE-WAIT

这类情况其实很简单,就是服务端没有发送FIN报文导致,一般来说就是程序有BUG,需要修复。一般的表现就是客户端因为时间太久发送了关闭连接的请求,但是服务端因为某些原因没有关闭该链接。

所以,找BUG吧。

7. TCP数据传输

7.1. 数据合并

操作系统会进行判断,尽快采用数据捎带ACK的传输方式。

7.2. seq & ack

需要注意的是:

  • seq其实是相对于自己而言的
  • ack是相对于对端发送的数据而言的。

7.3. 滑动窗口

对于TCP通信而言,并不是发送一个报文,接收ACK后再发送下一个,这样的效率实在是太低了,所以TCP通信时会持续发送,并持续等待应答,如下图的情况:

这样就可以同时发送多个报文,在不需要等待上个报文回复的情况下,但对应的,需要发送方维护一个信息,信息中需要包含已发送和确认的关系。

滑动窗口在每个报文中都有,用来表示此报文的发送方能够接收的数据大小(单位:字节)。此机制可以控制对方发送数据的频率,从而达到流量控制的效果,这个值是一个16bit,最大值为65535,如果超过这个值就需要使用到window scale选项。

对于接收方而言:

  • 已接收已确认表示报文已经收到,并且回复了ACK,之所以还在buf中,应该是应用程序还没有取走;
  • 等待接收未确认标识报文还没有收到,但也不完全是,因为报文可以不按照顺序发送过来,例如图中的8/9,由于TCP协议是基于seq和ack来确认顺序的,所以此时接收到的报文8/9不能确认,那么就只能等6/7报文到达,等6/7报文到达后,会回复ACK,此时的6/7/8/9都会变为已接收已确认的状态;
  • 不能接收的表示超过了操作系统设置的最大buf,如果说应用程序将已接收已确认的数据取走,那么16就可以接收了。

Window Size在接收方中描述的就是等待接收未确认的buf大小。

对于发送方而言:

  • windows大小表示的是已发送未确认和未发送可发送的大小;
  • 对于已发送已确认的消息,操作系统会将其移除;
  • 在传统IO模型中,用户要发送的数据会首先在用户空间,内核会根据自己的Buf大小,选择移动部分数据至自己的socker缓冲区;

8. UDP报文格式

https://www.rfc-editor.org/rfc/rfc768

UDP即User Datagram Protocol,它的报文格式如下:

                 0      7 8     15 16    23 24    31+--------+--------+--------+--------+|     Source      |   Destination   ||      Port       |      Port       |+--------+--------+--------+--------+|                 |                 ||     Length      |    Checksum     |+--------+--------+--------+--------+||          data octets ...+---------------- ...User Datagram Header Format

  • Source Port:源端口;
  • Destination Port:目的端口;
  • Length:总长度,即UDP报文的长度,为IP总长度-IP首部长度,主要是为了解析方便;
  • Checksum:校验和。

因为UDP数据结构太简单了,Checksum在校验时会出现一些无法识别的伪造,或者说太容易碰撞了,所以实际中校验和会讲UDP头部加上IP头的部分内容合并在一起计算校验和,一般包括了源IP、目的IP、协议号,UDP长度等信息。

9. 数据分片

9.1. 那一层能分片

要分片,首先得需要支持重组,那么对应着协议的结构,首先需要明确的是哪些层可以分片:

  • 以太帧:不支持分片,没有对应的字段;
  • IP报文:支持分片,有Fragment Offset、DF、MF等标识;
  • TCP报文:支持分片,有Data Offset;
  • UDP报文:不支持分片,没有对应的字段。

9.2. IP分片

一般不建议IP分片,IP分片后如果在传输过程中丢失分片的话需要重传所有的数据。

IP报文的大小是根据MTU决定的,MTU其实是由双方决定的,假设在传输的过程中有一些网络设备不支持对应的MTU,那么这些设备就需要对IP报文进行分片。

假设存在这么一种情况:A ---1500---B---1024---C---1500---D

B-C间因为特殊的原因,其MTU为1024,从A发送到B的数据,必须进行分片才能发出去,因为B的出口是1024,那么B会有两种处理策略:

  • 假设DF == 0,表示允许分片,那么B会进行分片,到达目的地后由目的地节点重组;
  • 假设DF == 1,表示不允许分片,那么B会丢弃该报文,然后应答给A一个ICMP消息,Fragment Needed But DF Set,并在信息中包含1024(就是可以发送的大小),A收到后会进行分片,然后重新发送给B,转发至D端。

如果在中间的网络设备被分片了,假设丢包的话,对于目的端而言,它可以知道缺少了哪一片,但是发送方不一定知道,因为分片不是在发送方做的,就只能重传所有的数据。

9.3. TCP分片

TCP分片比较简单,核心就是处理MSS,发送方会按照对端的MSS对数据进行分片,如果缺少了某个分片,只需要重传这个分片即可,不需要,加快了处理效率。

实际使用中建议TCP分片,而将IP设置为不分片的模式。

9.4. UDP分片

UDP协议本身是不支持分片的,但是可以通过IP层进行分片,这样就变相实现了分片的能力。

但是考虑到IP层分片在丢包时需要整体重传的弊端,所以还是不建议分片,换句话说,在使用UDP协议时尽量发送少了的数据,避免IP分片的风险。推荐300-500字节。

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

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

相关文章

cookie实战案例-自动登录网站

在写爬虫的时候,要伪装成真实用户请求。可能需要大量的IP地址,那么大量的IP地址从哪里来呢?这里就需要用代理IP来解决了,有的网站专门通过提供代理IP池服务作为主要的经营业务,只要注册相关网站开通对应套餐就可以了。…

Java笔试面试题AI答之JDBC(1)

文章目录 1. 什么是JDBC?2. 驱动(Driver)在JDBC中的角色?3. JDBC PreparedStatement比Statement有什么优势?1. 预编译和性能提升2. 参数化查询和安全性3. 更好的可读性和可维护性4. 支持批量操作5. 缓存机制(特定数据库环境&#…

2024 高教社杯 数学建模国赛 (A题)深度剖析|“板凳龙” 闹元宵|数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时,你是否曾经感到茫然无措?作为2022年美国大学生数学建模比赛的O奖得主,我为大家提供了一套优秀的解题思路,让你轻松应对各种难题! CS团队倾注了大量时间和心血,深入挖掘解…

2024 年高教社杯全国大学生数学建模竞赛题目-D 题 反潜航空深弹命中概率问题

应用深水炸弹(简称深弹)反潜,曾是二战时期反潜的重要手段,而随着现代军事技术 的发展,鱼雷已成为现代反潜作战的主要武器。但是,在海峡或浅海等海底地形较为复杂的 海域,由于价格低、抗干扰能力…

读懂以太坊源码(4)-详细解析节点配置文件geth.toml

要读懂以太坊源码,先熟悉配置文件的每个配置项也是非常有必要的,以下代码是以太坊主网配置文件(geth.toml)的完整内容,后面是对每个配置项的说明: [Eth] NetworkId 0 SyncMode "snap" EthDiscoveryURLs [] SnapDisc…

14 C语言实现平衡二叉树

//LL型失衡 右旋 //RR型失衡 左旋 //RL型失衡 先右旋 再左旋 //LR型失衡 先左旋 再右旋 #include "stdio.h" #include "stdlib.h"typedef int ElemType; typedef struct node {ElemType data;int height;struct node *left;struct node *right; } Node;Nod…

SpringBoot生成ETH和ERON钱包

首先大家需要先引入相关依赖包,这个maven里面是没有的,需要我们自行导入才可以。在项目路径下面创建lib,将所有需要使用的包导入即可。给大家一个包的下载链接:https://download.csdn.net/download/qq_38935605/89715772 因为放在…

scrapy 爬取微博(一)【最新超详细解析】:创建微博爬取工程

本项目属于个人学习记录,爬取的数据会于12小时内销毁,且不可用于商用。 1 初始化环境 首先我们需要有python环境,先安装一下python,然后配置环境变量,这边给出windows的配置: 我这边的安装目录是D:\pyt…

关于SPI通信失败的一种情况(CRC校验不匹配的问题)

问题 该项目中,使用外置的ADC芯片采集电压电流,主控MCU通过SPI与ADC芯片通信。调试时,SPI通信一直失败,与之前成功的项目对比,发现是SPI配置的问题。 void MX_SPI2_Init(void) {/* USER CODE BEGIN SPI2_Init 0 *//*…

WIFI贴项目到底是不是“骗局”呢?由我来揭秘!

各位亲爱的朋友们,大家好!我是你们的老朋友鲸天科技千千,一直在这片互联网的热土上耕耘。相信你们对我都不会陌生,因为我常常分享一些互联网上的新奇项目和实用技巧。如果你对我的内容感兴趣,别忘了点个关注哦&#xf…

【案例67】Npart批量启动服务卡顿严重分析过程

问题现象 通过Npart启动NC服务,发现只启动一个,大概3min左右即可启动成功。但是批量启动服务需要几十分钟才可以把服务启动成功,启动卡在获取“wenjian”图标处。 绕过Npart直接写脚本并行启动相关服务,发现也需要30min 问题分析…

数组与贪心算法——605、121、122、561、455、575(5简1中)

605. 种花问题(简单) 假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。 给你一个整数数组 flowerbed 表示花坛&#xf…

网络传输加密及openssl使用样例(客户端服务器)

文章目录 背景常用加密方式SSLOpenSSL主要功能 库结构 交互流程证书生成生成 RSA 私钥私钥的主要组成部分私钥的格式 创建自签名证书: 签发证书服务器端代码客户端代码常见错误版本问题证书问题证书格式 背景 网络传输中为保证数据安全,通常需要加密 常用加密方式…

1.初识ChatGPT:AI聊天机器人的革命(1/10)

引言 在当今的数字化世界中,人工智能(AI)正以其独特的方式重塑我们的生活和工作。其中,AI聊天机器人作为人机交互的前沿技术,已经成为企业与客户沟通、提供个性化服务的重要工具。这些机器人通过模拟人类的对话方式&a…

【Unity3D优化】优化内置shader的内存占用

一、性能分析 监控项目线上的崩溃情况,绝大多数崩溃都是因为低端设备,运行时内存不足,在运行过程中申请开辟新的内存时Crash了。因此,不定期继续优化内存占用。 性能分析首先主要靠Unity3d的Memory Profiler监控一些可追踪到的内存…

Java 方法的定义

目录 1.Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段。 2.方法包含一个方法头和方法体,下面是一个方法的所有部分: (1)修饰符:可选。告诉编译器如何调用该方法,定义了该…

基于微信小程序的挂号管理系统-小程序端

微信小程序端系统功能实现 登录功能 系统登录功能中,用户只需在登录界面输入正确的用户名和密码,即可快速进入系统。登录功能还采用了先进的加密技术,保障用户信息的安全性,让用户能够放心使用。 注册功能 系统注册功中&#xf…

Vue项目“npm run serve”总卡住的问题 已解决

Vue项目“npm run serve”总卡住的问题 已解决 概述 如果卡住进度在51% 直接看这篇 https://blog.csdn.net/qq_34419312/article/details/141681307?spm1001.2014.3001.5501 在使用Vue.js进行项目开发时,npm run serve命令是我们常用的启动本地开发服务器的方式…

使用docker compose一键部署 Openldap

使用docker compose一键部署 Openldap LDAP(轻量级目录访问协议,Lightweight Directory Access Protocol)是一种用于访问分布式目录服务的网络协议,OpenLDAP 是 LDAP 协议的一个开源实现,由 OpenLDAP 项目提供&#x…

虚幻5|技能栏UI优化(3)——优化技能UI并实现显示背景UI,实现技能界面设计,实现技能栏的删除和添加

实现技能栏添加:将技能界面里的技能拖到技能栏格子 一.调整,在拖出技能的时候,还会有边框 1.打开拖拽的技能格子UI 除了技能按钮,下面的子级都放到垂直框的子级,然后删除技能按钮 2.将垂直框替换成包裹框 你会发现有…