基础知识_网络

文章目录
  1. 1. 网络的分层结构
  2. 2. IP协议头部
  3. 3. TCP协议头部
  4. 4. TCP的重传机制
  5. 5. TCP的流量控制
  6. 6. TCP的滑动窗口
  7. 7. TCP拥塞控制的几个算法
  8. 8. TCP三次握手与四次挥手的过程
  9. 9. 为什么需要三次握手和四次挥手
  10. 10. TCP的状态机
  11. 11. TIME_WAIT状态
  12. 12. TCP长连接和短连接
  13. 13. web服务器/TCP接受连接的最大数量
  14. 14. TCP粘包问题
  15. 15. UDP协议头部
  16. 16. QUIC协议
  17. 17. TCP和UDP的区别
  18. 18. HTTP消息格式
  19. 19. HTTP请求头部中有哪些字段
  20. 20. HTTP的状态码
  21. 21. 介绍一下https协议
  22. 22. ping命令的原理
  23. 23. 点击网页上的登录按钮后,发生了什么
  24. 24. 系统收到数据到交付应用程序的整个过程
  25. 25. 应用层协议常用的端口
  26. 26. 建立TCP服务器的系统调用
  27. 27. one thread one loop思想

计算机网络基础知识与常见题目。

网络的分层结构

  • OSI七层模型

    1
    2
    3
    4
    5
    6
    7
    应用层 |
    表示层 } 数据
    会话层 |
    传输层:分段
    网络层:分组数据报
    数据链路层:帧
    物理层:比特流
  • TCP/IP四层模型

    1
    2
    3
    4
    应用层
    运输层
    网际层
    网络接口层
  • 五层

    1
    2
    3
    4
    5
    应用层:http、ftp、smtp、telnet
    传输层:tcp、udp
    网络层:IP
    数据链路层:
    物理层:IEEE802.2、Ethernet v.2

IP协议头部

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|--------------------------------------------------------------------------------------|----|-----------------
| Version 4bits | IHL 4bits | 区分服务8位 | 总长度16位 | | 首部
|--------------------------------------------------------------------------------------| |
| 标识 | 标志2位 | 片偏移 | 固定部分
|--------------------------------------------------------------------------------------| 20个字节
| 生存时间TTL | 上层协议 | 首部校验和 | |
|--------------------------------------------------------------------------------------| |
| 32位源IP地址 | |
|--------------------------------------------------------------------------------------| |
| 32位目的IP地址 | |
|--------------------------------------------------------------------------------------|----|
| 可选字段(长度可变) | 填充 |
|--------------------------------------------------------------------------------------|-----------------------
| 数据部分 |
|--------------------------------------------------------------------------------------|
  • 基本的ip头部长度为20字节,可变长度的选项最多可达40字节,ip头部总长最多60字节,ip数据最多65515字节。
  • 第一个字段是版本字段,占4位。记录本数据报是ipv4还是ipv6.
  • IHL(Internet head length)是头部长度字段,占4位。记录数据报头部中32位字的数量。所以最多只能表示60个字节.
  • DS字段和ECN字段在最初是统称为服务类型(ToS)字段,后来才分成两个。
  • DS(Differentiated Services)为区分服务字段,占6位。这个字段是用来提供差异化服务的,以给数据报提供不同的优先级。
    6位中最后一位是1,表示实验或本地用途;以0结尾表示标准用途。前5位对流量类别和丢弃优先级进行了区分,具体参考RFC2474/2597/3246/5865.
  • ECN(Explicit Congestion Notification)显式拥塞通知字段,占2位。在数据报传输途中,如果一台具有拥塞感知功能的路由器检测到了拥塞,就会设置这2位,以此来通知目的主机,目的主机接收到之后会通知发送方降低发送速度。
  • 总长度字段记录数据报的总长度,长度16位,可以表示ipv4数据报的最大长度为65535字节。通过这个字段和IHL字段,可以知道数据报的数据部分从哪里开始。
  • 标示、标志、分片偏移三个字段对ip数据报的分片至关重要。
  • 16位的标示字段,是用来标记数据报的分片的。发送方主机在每次发送数据报时,会将本地计数器的值加1,然后存到该字段。如果该数据报在传送途中被分片,每个分片会分别复制这个值,目的主机接收到这些分片,就可以根据这个标示来判断哪些数据报是一伙的。
  • 3位标志字段分别是保留位、DF(don’t frame)、MF(more frame)。DF为1表示本数据报不能分片。MF为1表示后面还有分片,MF为0表示这是最后一个分片。
  • 13位的分片偏移字段,记录该数据报分片之前的位置。
  • 生存期(TTL)字段用来设置一个数据报可能经过的路由器数量上限。每台路由器再转发数据报时会将该值减1,如果达到0,就丢弃该数报并用一个ICMP消息通知发送方。
  • 8位的上层协议字段用来标示ip数据报所承载的数据报类型,17为udp,6为tcp,4表示ipv4.
  • 16位首部校验和字段仅计算ipv4的头部。所以内部的tcp等数据报需要自己记录本身的校验和。另外由于TTL字段每经过一台路由器就要减1,导致每次需要重新计算校验和。
  • 剩下的两块为源ip地址和目的ip地址。
    IP协议详解

TCP协议头部

1
2
3
4
5
6
7
8
9
10
11
12
13
|-------------------------------------------------------------------------------------|
| 16位源端口号 | 16位目的端口号 |
|-------------------------------------------------------------------------------------|
| 序列号 |
|-------------------------------------------------------------------------------------|
| 确认号(acknowledgement number) |
|-------------------------------------------------------------------------------------|
| 4位头部长度|6位保留| 6个标志位 | 16位窗口大小 |
|-------------------------------------------------------------------------------------|
| 16位校验和 | 16位紧急指针 |
|-------------------------------------------------------------------------------------|
| 选项信息 最多40字节 |
|-------------------------------------------------------------------------------------|
  • 16位源端口号和16位目的端口号。
  • 32位序列号,用来标识数据的序号。
  • 32位确认号比如收到的上个数据包的序列号是n,那这里的确认号就是n+1.
  • 4位头部,标识该tcp头部有多少个4字节,最长15*4=60个字节,同IP协议头部。
  • 6位保留。
  • 6位标志,URG:紧急指针是否有效,ACK:确认号是否有效,PSH:提示接收端应用程序应立即从缓冲区读数据,RST:要求对方重新建立连接,SYN:请求建立连接,FIN:通知对方本端要关闭连接。
  • 16位窗口大小,用于流量控制的字段。
  • 16位校验和。
  • 16位紧急指针,是一个正的偏移字节量。序列号+偏移量为带外数据的位置。(带外数据的应用场景是什么?)

TCP的重传机制

1.超时重传
顾名思义,如果检测到某一个数据包的定时器超出时间RTO(Retransmission Timeout超时重传时间)了,就需要重新发送该数据包了,RTO是由RTT计算出来的。RTT(Round-Trip Time 往返时延)这是从发送一个消息直到收到确认的时间。下面是RTO的计算方式:
RTO计算方式
其中 SRTT 是计算平滑的RTT ,DevRTR 是计算平滑的RTT 与 最新 RTT 的差距。在 Linux 下,α = 0.125,β = 0.25, μ = 1,∂ = 4。这是通过实验选定的系数。
如果对数据重传之后,再设定的超时时间是原来的2倍。
2.快速重传
等着计时器超时会浪费一些不必要的时间,如果发送方发送1、2、3、4、5数据包,当1丢失后,接收方收到234数据包,会回复三次ACK=1,发送方收到三次相同的ack,就知道1数据包丢了,于是重新发送1号数据包。
但是如果1号2号数据包都丢失了,345数据到达接收方时,接收方还是回复三次ACK=1,这时如果只重传1号数据包是不够的。于是有了SACK方法。
3.SACK方法
SACK(Selective Acknowledgment 选择性确认),是在接收方回复的ACK中,TCP头部的”选项”字段里,添加SACK字段,用来标识哪些数据被接收了。例如当发送方发送1-5数据,1、2号数据丢失,当接收方收到3号数据,回复ACK=1,SACK=3。接收方收到4号数据,回复ACK=1,SACK=3-4。接收方收到5号数据,回复ACK=1,SACK=3-5.这样发送方明白3-5已经发送成功,只需要重传1-2号数据。
SACK是解决”丢失多个发送方->接收方的数据包”问题。
4.Duplicate SACK
D-SACK是在接收方回复ACK确认的时候,借助TCP头部”选项”里的SACK字段,标识哪些数据被重复发送了。例如,当发送方发送1-5数据,接收方回复的ACK=1和ACK=2丢失了,超时之后发送方会重复发送1、2数据,此时接收方回复ACK=3,SACK=1-2。这时发送方看到ACK是3,大于1、2,说明1-2数据是被重复发送了。
D-SACK是解决”丢失多个接收方->发送方的ACK确认”问题。

TCP的流量控制

发送方应当根据接收方的处理能力来发送数据,如果接收方的应用程序读取数据速度下降,接收窗口的可用空间就会变小,于是发送方对应的会减小发送窗口的大小。
1.如果接收方的应用程序没有及时读取缓存,接收窗口不断下降,最终下降到0,这样发送窗口也被调整为0了。之后发送方应当发送探测报文,不然可能会死锁下去。为了解决这个死锁问题,TCP 为每个连接设有一个持续定时器,只要TCP 连接一方收到对方的零窗口通知,就启动持续计时器。如果持续计时器超时,就会发送窗口探测(Window probe) 报文,而对方在确认这个探测报文时,给出自己现在的接收窗口大小。
2.如果接收方直接减小了缓存大小,也就是接收窗口的大小,发送方已经发送的一部分数据,还没确认,可能就因为降低窗口大小,被丢弃了。
3.接收方处理能力下降后,有可能出现这样一种情况,接收方通知发送方一个小的窗口大小,然后发送方发送很小的数据。这样可能只为了几个字节的数据就加上几十个自己的协议头部,开销还是挺大的。TCP使用的解决方法是不让接收方通知小窗口&不让发送方发送小数据。如果接收方的接收窗口小于min(MSS,缓存的一半),就直接通告0窗口,发送方判断的接收方窗口如果大于MSS或者自己储存的数据量大于MSS(Nagle算法),才开始发送数据。

TCP的滑动窗口

  • 滑动窗口要解决的问题:1.如果发送方发送一个数据包a,等收到接收方的确认再发送下一个数据包b。这样效率太低了。2.于是改成连着发送abcd多个数据包,但是又有可能到达接收方时的顺序bacd,所以还要保证数据在两端的顺序相同且无丢包
  • 滑动窗口有两个,分别是发送窗口和接收窗口,发送窗口不能超过接收窗口。
  • 发送窗口分为两部分,前面一段是已发送但未收到ACK确认的数据,后一段是马上要发送并且在接收方处理范围内。发送窗口左边的的数据是已发送并收到ACK确认的,发送窗口右边的是以后要被发送的。
    如下图,SND.WND是发送窗口的大小,SND.UNA指向已发送但未收到ACK确认的第一个字节,SND.NXT指向未发送但马上要发送的第一个字节。
    发送窗口
    如果收到对5个字节数据的ACK确认,发送窗口就会往右滑动5个字节。
  • 接收窗口只有一部分,表示还未收到但正准备接收的数据。接收窗口左边的是已经接收并回复确认的数据,右边是未接收并且现在还无法接收的数据。
    接收窗口
    参考:https://mp.weixin.qq.com/s/Tc09ovdNacOtnMOMeRc_uA

TCP拥塞控制的几个算法

首先要知道拥塞窗口的概念,对应的还有个发送窗口的概念。发送窗口swnd’(这是参考值)的大小是根据接收方的接收能力来定的。而拥塞窗口cwnd是根据线路的拥堵程度确定的。实际的发送窗口大小是swnd=min(swnd’,cwnd)。以下几个算法便是用来设置拥塞窗口的值:

  • 慢启动
    慢启动的意思是,初始cwnd是1,之后每收到接收方一个ACK,就将cwnd的大小加1。所以慢启动过程是这样的:一开始cwnd=1,收到1个ACK确认,然后cwnd变成2。接着发送2个数据包,收到2个ACK确认后cwnd变成4。之后是8、16…(所以慢启动并不是说增长的速度慢,而是刚开始发送少量数据包。)
  • 拥塞避免
    在慢启动算法中,cwnd是以指数级别变大的,增长速度很快的,当然不能让它这样增长下去。于是设置了一个慢启动门限ssthresh(slow start threshold)状态变量,当cwnd到达慢启动门限后,就启用拥塞避免算法:它的规则是每收到1个ACK,cwnd增加1/cwnd,换言之,每发送cwnd个数据包,收到cwnd个确认后,cwnd加1.
    拥塞避免
  • 拥塞发生
    当网络状况不好时,需要重传数据包,有两种情况:
    当线路拥塞程度比较低时,发送方发送abcd四个数据包,只丢失了a,接收方会在收到bcd后,回复三次ACK=a,发送方检测到三次重复的ACK确认后,知道数据包a丢失了,但是能收到三次ACK说明线路状况还不至于太差。于是启动快速重传算法,将cwnd=cwnd/2,ssthresh=cwnd。这样的结果就是检测到少量丢包,就切换到快速恢复算法(意味着之后会切换到拥塞避免算法)。
    拥塞发生->拥塞避免
    当拥塞程度高的时候,发送方发送abcd四个数据包,全部丢了。等发送方的计时器超时了,就知道数据包都丢了或者说接收方回复的ACK确认都丢了。这时候使用超时重传算法,将慢启动门限ssthresh设置为cwnd/2,cwnd设置为1.这样的结果就是检测到消息超时了,就切换到慢启动算法上了。
    拥塞发生->慢启动
  • 快速恢复
    当超时重传后,cwnd直接变成1了,这样就传输速度一下子就降到很低了。如果只是少量丢包,也那样处理就反应过度了,所以快速重传后,使用快速恢复算法:cwnd=ssthresh+3(3代表刚收到的三个重复的ACK确认),这样cwnd是大于ssthresh的,之后执行的就是拥塞避免算法了。
    参考:https://mp.weixin.qq.com/s/Tc09ovdNacOtnMOMeRc_uA

TCP三次握手与四次挥手的过程

  • 第一次握手:client设置syn包中的同步序列号SYN=i,然后将syn包发送到服务器,并进入SYN_SENT状态,等待服务器确认。
  • 第二次:服务器收到syn包,需要进行确认,设置(ack=i+1),同时自己也发一个syn包(SYN=j),即发送SYN+ACK包,然后服务器进入SYN_RECV状态。
  • 第三次:客户端收到SYN+ACK包之后,向服务器发送ACK包(ack=j+1)进行确认,然后客户端和服务器都会进入ESTABLISHED状态,完成三次握手。
  • 传输数据
  • 第一次挥手:主动关闭方A发送FIN包(seq=a).
  • 第二次:被动关闭方B回复ACK包(seq=a+1).
  • 第三次:B成为新的主动关闭方,向A发送FIN包(seq=b)
  • 第四次:A回复ACK包(seq=b+1)

为什么需要三次握手和四次挥手

1.三次握手

  • 三次握手本质上是要建立一个对序列号的共识(双方对一件事情共同认可),因为之后要保证数据的可靠和顺序。
  • 四次握手有点多余,可以简化:
    1
    2
    3
    4
    5
    四次握手是这样的:
    client>>server:SYN=a
    client<<server:ACK=a+1
    client<<server:SYN=b
    client>>server:ACK=b+1

前两次握手,双方对client的序号产生了共识,后两次握手,双方对server的序号产生共识,这样tcp双向的传输通道建立。第二次和第三次握手可以直接放一块发送,这样简化为三次就可以了。

  • 两次握手不够,会出问题:
    1
    2
    3
    两次握手:
    client>>server:SYN=a
    client<<server:ACK=a+1,SYN=b

(1)如果第二次握手的数据丢失了,server会以为成功建立了连接,但是client没有收到确认,所以会尝试重新发送SYN请求。server收到第二次SYN请求,以为是要再次建立连接就回复ACK,于是server就维护两个连接了。这样二次握手可能会导致server端单方面建立许多并不成功的连接。
(2)如果第一次握手的信息package1在网络中滞留了,client检测超时后会重新发送SYN,server回复ACK确认,这样成功建立连接了。但这时已经失效的package1又到达了server,server不知道这是失效的请求,又会回复ACK建立连接。当client接收到第二个ACK,知道server端用失效的SYN建立了连接,只能干着急。
2.四次挥手

  • 因为TCP连接是全双工的,客户端想要断开连接,服务器回复确认。这样就断开了客户端往服务器方向的连接,但是服务器可能还需要给客户端发送数据,所以第二次第三次挥手不能合并。
    3.补充阅读
    1
    2
    3
    4
    5
    6
    7
    8
    第一个包,即A发给B的SYN 中途被丢,没有到达B
    A会周期性超时重传,直到收到B的确认
    第二个包,即B发给A的SYN +ACK 中途被丢,没有到达A
    B会周期性超时重传,直到收到A的确认
    第三个包,即A发给B的ACK 中途被丢,没有到达B.A发完ACK,单方面认为TCP为 Established状态,而B显然认为TCP为Active状态:
    a. 假定此时双方都没有数据发送,B会周期性超时重传,直到收到A的确认,收到之后B的TCP 连接也为 Established状态,双向可以发包。
    b. 假定此时A有数据发送,B收到A的 Data + ACK,自然会切换为established 状态,并接受A的 Data。
    c. 假定B有数据发送,数据发送不了,会一直周期性超时重传SYN + ACK,直到收到A的确认才可以发送数据。

4.参考

TCP的状态机

TCP状态转换图1
TCP状态转换图2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
上半部分是TCP三路握手过程的状态变迁,下半部分是TCP四次挥手过程的状态变迁。
CLOSED:起始点,在超时或者连接关闭时候进入此状态,这并不是一个真正的状态,而是这个状态图的假想起点和终点。
LISTEN:服务器端等待连接的状态。服务器经过 socket,bind,listen 函数之后进入此状态,开始监听客户端发过来的连接请求。此称为应用程序被动打开(等到客户端连接请求)。
SYN_SENT:第一次握手发生阶段,客户端发起连接。客户端调用 connect,发送 SYN 给服务器端,然后进入 SYN_SENT 状态,等待服务器端确认(三次握手中的第二个报文)。如果服务器端不能连接,则直接进入CLOSED状态。
SYN_RCVD:第二次握手发生阶段,跟 3 对应,这里是服务器端接收到了客户端的 SYN,此时服务器由 LISTEN 进入 SYN_RCVD状态,同时服务器端回应一个 ACK,然后再发送一个 SYN 即 SYN+ACK 给客户端。状态图中还描绘了这样一种情况,当客户端在发送 SYN 的同时也收到服务器端的 SYN请求,即两个同时发起连接请求,那么客户端就会从 SYN_SENT 转换到 SYN_REVD 状态。
ESTABLISHED:第三次握手发生阶段,客户端接收到服务器端的 ACK 包(ACK,SYN)之后,也会发送一个 ACK 确认包,客户端进入 ESTABLISHED 状态,表明客户端这边已经准备好,但TCP 需要两端都准备好才可以进行数据传输。服务器端收到客户端的 ACK 之后会从 SYN_RCVD 状态转移到 ESTABLISHED 状态,表明服务器端也准备好进行数据传输了。这样客户端和服务器端都是 ESTABLISHED 状态,就可以进行后面的数据传输了。所以 ESTABLISHED 也可以说是一个数据传送状态。
上面就是 TCP 三次握手过程的状态变迁。结合第一张三次握手过程图,从报文的角度看状态变迁:SYN_SENT 状态表示已经客户端已经发送了 SYN 报文,SYN_RCVD 状态表示服务器端已经接收到了 SYN 报文。

下面看看TCP四次挥手过程的状态变迁。结合第一张四次挥手过程图来理解。
FIN_WAIT_1:第一次挥手。主动关闭的一方(执行主动关闭的一方既可以是客户端,也可以是服务器端,这里以客户端执行主动关闭为例),终止连接时,发送 FIN 给对方,然后等待对方返回 ACK 。调用 close() 第一次挥手就进入此状态。
CLOSE_WAIT:接收到FIN 之后,被动关闭的一方进入此状态。具体动作是接收到 FIN,同时发送 ACK。之所以叫 CLOSE_WAIT 可以理解为被动关闭的一方此时正在等待上层应用程序发出关闭连接指令。前面已经说过,TCP关闭是全双工过程,这里客户端执行了主动关闭,被动方服务器端接收到FIN 后也需要调用 close 关闭,这个 CLOSE_WAIT 就是处于这个状态,等待发送 FIN,发送了FIN 则进入 LAST_ACK 状态。
FIN_WAIT_2:主动端(这里是客户端)先执行主动关闭发送FIN,然后接收到被动方返回的 ACK 后进入此状态。
LAST_ACK:被动方(服务器端)发起关闭请求,由状态2 进入此状态,具体动作是发送 FIN给对方,同时在接收到ACK 时进入CLOSED状态。
CLOSING:两边同时发起关闭请求时(即主动方发送FIN,等待被动方返回ACK,同时被动方也发送了FIN,主动方接收到了FIN之后,发送ACK给被动方),主动方会由FIN_WAIT_1 进入此状态,等待被动方返回ACK。
TIME_WAIT:从状态变迁图会看到,四次挥手操作最后都会经过这样一个状态然后进入CLOSED状态。共有三个状态会进入该状态
*由CLOSING进入:同时发起关闭情况下,当主动端接收到ACK后,进入此状态,实际上这里的同时是这样的情况:客户端发起关闭请求,发送FIN之后等待服务器端回应ACK,但此时服务器端同时也发起关闭请求,也发送了FIN,并且被客户端先于ACK接收到。
*由FIN_WAIT_1进入:发起关闭后,发送了FIN,等待ACK的时候,正好被动方(服务器端)也发起关闭请求,发送了FIN,这时客户端接收到了先前ACK,也收到了对方的FIN,然后发送ACK(对对方FIN的回应),与CLOSING进入的状态不同的是接收到FIN和ACK的先后顺序。
*由FIN_WAIT_2进入:这是不同时的情况,主动方在完成自身发起的主动关闭请求后,接收到了对方发送过来的FIN,然后回应 ACK。

参考:https://blog.csdn.net/wenqian1991/article/details/40110703

TIME_WAIT状态

主动关闭连接的那一方最后会进入TIME_WAIT状态,这个状态可以解决两个问题:

  • 保证连接被可靠地关闭。主动关闭连接的一方先发送FIN,收到ACK。然后再收到被动方的FIN,需要回复ACK,但是最后这个ACK有可能被丢失,TIME_WAIT状态持续了2MSL时间,如果最后的ACK丢失了,被动方没有收到ACK,然后会重新发送FIN,这样主动方可以重新发送ACK确认。保证连接被可靠地关闭。
  • 保证网络中没有残留的报文干扰之后的连接。如果客户端主动断开连接,之后四次挥手连接关闭了。但这是如果网络中还有残存的数据包,然后客户端和服务端又重新建立连接后,使用的还是之前的IP地址和端口号,这时数据包又到达了,此时连接就会被干扰。

TCP长连接和短连接

  • TCP本身只是面向连接的,长连接和短连接取决于我们如何使用。
  • 短连接:如果我们在三次握手后,进行一次传输,然后就四次挥手关闭连接,可以认为这是一次短连接。如果再需要传输,就再建立一次连接。
  • 长连接:对于传输频率比较频繁的场景,用短连接就不适合了。此时应当是三次握手..传输数据…传输数据..四次挥手,这叫做长连接。这样又有一个问题,连接需要一直保持着,如果客户端断网了或者死机了,服务器可以释放这个连接的资源。
  • 保活机制:这样就有一个保活机制,来让服务端检测客户端是否在线。tcp附带了一个keepalive机制,默认一个连接在两个小时内没有任何动作,服务器就向客户端发送一个探测。
    1.如果收到回复,则将定时器再设置两个小时。
    2.如果客户端崩溃或者关机或者重启,服务器会每隔75秒,总共发送10个探测,如果没有收到一个响应,就关闭连接。
    3.如果客户端崩溃并重新启动了,客户端会给服务端回复一个复位信息,让服务器终止连接。
    4.如果客户端正常,中间线路出现问题,对于服务器来说,这与情况2相同对待。
  • 应用层保活机制:?
  • 应用场景:?
  • http://docs.52im.net/extend/docs/book/tcpip/vol1/23/

web服务器/TCP接受连接的最大数量

  • tcp有一个监听套接字负责监听,如果调用accept接受了一个连接,就为其新创建一个套接字描述符,tcp并不会受端口数限制,它可以用一个端口跟多个客户端通讯,所以连接数量是受内存大小限制,或进程的设置的限制。

TCP粘包问题

UDP协议头部

1
2
3
4
5
6
7
8
9
10
11
12
13
|-------------------------------------------------------------------------------------|---
| 32位源IP地址 |
|-------------------------------------------------------------------------------------| UDP伪首部
| 32位目的IP地址 | (伪首部是计算校验和用的)
|-------------------------------------------------------------------------------------|
| 0 | 8位协议 | 16位UDP长度 |
|-------------------------------------------------------------------------------------|-------------------------
| 16位源端口号 | 16位目的端口号 |
|-------------------------------------------------------------------------------------|
| 16位UDP长度 | 16位UDP校验和 | UDP首部
|-------------------------------------------------------------------------------------|
| 数据 |
|-------------------------------------------------------------------------------------|---

QUIC协议

http://leungyukshing.cn/archives/QUIC.html

TCP和UDP的区别

TCP UDP
面向连接的、可靠的传输 无连接、不可靠的传输
面向字节流,有一个缓冲区来储存字节序列 面向报文的,来一个报文就发送
只能是点对点的 可以一对一、一对多、多对多
有三次握手、确认、拥塞控制、流量控制等机制来保证可靠传输 没有这些机制
占用资源多,速度慢 速度快
适合对数据可靠性要求严格的场景,如传输文件、网页 适合对时间要求严格的

HTTP消息格式

1.http请求可以分为三部分,第一部分是请求行,第二部分是请求头部,由一个个的key-value组成,第三部分是请求包体。

1
2
3
4
5
6
请求方法 URL 协议版本 <回车符换行符>
头部字段1 : 值1 <回车符换行符>
... : ...
头部字段n : 值n <回车符换行符>
<空行>
请求包体

样例:

1
2
3
4
5
6
7
8
9
GET/sample.Jsp HTTP/1.1
Accept:image/gif.image/jpeg,*/*
Accept-Language:zh-cn
Connection:Keep-Alive
Host:localhost
User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)
Accept-Encoding:gzip,deflate

username=jinqiao&password=1234

2.http相应格式也分为三部分,分别是状态行、响应头部、响应包体。

1
2
3
4
5
6
协议版本 状态码 状态码描述 <回车符换行符>
头部字段1 : 值1 <回车符换行符>
... : ...
头部字段n : 值n <回车符换行符>
<空行>
响应包体

样例:

1
2
3
4
5
6
7
8
9
HTTP/1.1 200 OK
Date: Mon, 10 Aug 2020 09:45:14 GMT
Server: Apache/2.4.6
Last-Modified: Wed, 04 Dec 2013 11:03:37 GMT
ETag: 1386155017
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

HTTP请求头部中有哪些字段

Accept : 浏览器(或者其他基于HTTP的客户端程序)可以接收的内容类型(Content-types),例如 Accept: text/plain
Accept-Charset:浏览器能识别的字符集,例如 Accept-Charset: utf-8
Accept-Encoding:浏览器可以处理的编码方式,注意这里的编码方式有别于字符集,这里的编码方式通常指gzip,deflate等。例如 Accept-Encoding: gzip, deflate
Accept-Language:浏览器接收的语言,其实也就是用户在什么语言地区,例如简体中文的就是 Accept-Language: zh-CN
Authorization:在HTTP中,服务器可以对一些资源进行认证保护,如果你要访问这些资源,就要提供用户名和密码,这个用户名和密码就是在Authorization头中附带的,格式是“username:password”字符串的base64编码,例如:Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==中,basic指使用basic认证方式,QWxhZGRpbjpvcGVuIHNlc2FtZQ==使用base64解码就是Aladdin:open sesame
Cookie:浏览器向服务器发送请求时发送cookie,或者服务器向浏览器附加cookie
Content-Length:一个请求的请求体的内存长度,单位为字节(byte)。请求体是指在HTTP头结束后,两个CR-LF字符组之后的内容,常见的有POST提交的表单数据,这个Content-Length并不包含请求行和HTTP头的数据长度。
Content-MD5:使用base64进行了编码的请求体的MD5校验和。例如:Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
User-Agent:通常就是用户的浏览器相关信息。例如:User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0

HTTP的状态码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1xx 代表请求已被接受,需要继续处理。但由于HTTP/1.0中没有定义任何1xx状态码,所以很少使用。
2×× 代表请求已成功被服务器接收、理解、并接受。
200 OK 请求成功
3xx 一般是用来重定向
302 暂时性转移
301 永久性转移
305 使用代理,所请求的资源必须通过代理访问
4xx 请求错误,一般是客户端导致的错误
400 Bad Request 当前请求有误,无法被理解
401 Unauthorized 当前请求需要用户验证
403 Forbidden 服务器已经理解请求,但是拒绝执行,比如访问了没有权限的目录。
404 Not Found 服务器没有找到所请求的资源
5xx 服务器内部错误
500 Internal Server Error :服务器正在执行请求时发生错误。
503 Service Unavailable :服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。

介绍一下https协议

  • https对消息进行了加密,还用证书来保证服务器不被冒充。
  • 首先了解两种密码体系,非对称加密,双方使用不同的密钥,计算量大,也更安全。对称加密计算量小,相对速度更快。
  • https是首先让双方通过非对称加密来交换一个密钥,之后用这个密钥对消息进行对称加密。
  • 在执行非对称加密时,客户端需要获取服务器的公钥,这个需要通过证书来保证公钥传输的安全。
  • 证书就是ca机构,用自己的私钥对服务器的公钥加密,客户端用ca的公钥解密后,获取服务器公钥。
  • 写一篇最好懂的HTTPS讲解
  • SSL协议的基本原理

ping命令的原理

利用ICMPv4协议实现一个ping程序

点击网页上的登录按钮后,发生了什么

  • DNS解析
      1.首先查找浏览器缓存,看是否有该网址对应的IP,如果有则返回IP,否则再去调用操作系统缓存。
      2.如果没找到,再发送请求到路由器上,如果有则返回。
      3.仍然没找到,请求就会被发送到DNS服务器。
    4.DNS的查询过程分别经过:浏览器缓存-操作系统缓存-路由器缓存-本地域名服务器-根域名服务器。
  • TCP连接
      向获取到的ip进行三次握手,获取tcp连接。
  • 浏览器发送HTTP请求
      1.浏览器构造http请求,然后发送到指定ip。
      2.http请求会分别被加上tcp头、ip头,然后发送出去。
  • 服务器接收请求并回复
      1.一层层把消息头去掉之后,获取到http请求。
      2.然后执行相应的请求,再进行回复。
  • 浏览器接收到html,进行解析和渲染页面
  • 四次挥手,关闭tcp连接

系统收到数据到交付应用程序的整个过程

??

应用层协议常用的端口

1
2
3
4
5
6
7
8
文件传输协议            ftp     21
安全shell ssh 22
远程登录协议 telnet 23
传输邮件服务 smtp 25
文本传输协议 http 80
访问远程服务器上的邮件 pop3 110
安全的超文本传输服务 https 443
dns 53

建立TCP服务器的系统调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tcp client      tcp server
socket socket
bind bind
connect listen
send accept
receive receive
send
========================
int socket(int protofamily, int so_type, int protocol);
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int listen(int sockfd, int backlog);
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
int accept (int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int send(int sockfd, const void *msg, int len, int flags);
int recv(int sockfd, void *buf, int len, unsigned int flags);

one thread one loop思想

翻译成中文的意思就是一个线程里面一个循环。一般可以让线程A接收新连接,然后将新连接的socket传给B1、B2、B3…来负责收发数据。一般的代码结构如下:

1
2
3
4
5
6
7
8
9
10
void thread_func(void* thread_arg)
{
//这里做一些需要的初始化工作
while (退出标志){
//步骤一:利用select/poll/epoll等IO复用技术,分离读写事件
//步骤二:处理读事件或写事件
//步骤三:做一些其他的事情
}
//这里做一些需要的清理
}

####

欢迎与我分享你的看法。
转载请注明出处:http://taowusheng.cn/