一、一些概念
1.1、局域网与广域网
- 局域网:局域网将一定区域内的各种计算机、外部设备和数据库连接起来形成计算机通信的私有网络。
- 广域网:又称广域网、外网、公网。是连接不同地区局域网或城域网计算机通信的远程公共网络。
1.2、IP
IP地址本质就是一个整数,用于表示计算机在网络中的地址。IPV4可以表示 2 32 2^{32} 232 个地址,IPV6可以表示 2 128 2^{128} 2128 个地址。
1.3、端口
端口的作用是定位到主机上的某一个进程,通过这个端口进程就可以接受到对应的网络数据了。
也就是一个进程对应一个端口,所以这也诞生了很多著名端口
- 80 - HTTP (HyperText Transfer Protocol):用于Web服务器默认的HTTP连接。
- 443 - HTTPS (HTTP Secure):用于安全的HTTP连接,通过TLS/SSL加密通信。
- 21 - FTP (File Transfer Protocol):用于文件传输。
- 22 - SSH (Secure Shell):用于安全的远程登录和文件传输。
- 25 - SMTP (Simple Mail Transfer Protocol):用于发送电子邮件。
- 110 - POP3 (Post Office Protocol version 3):用于接收电子邮件。
- 143 - IMAP (Internet Message Access Protocol):用于接收电子邮件。
- 53 - DNS (Domain Name System):用于域名解析。
- 3306 - MySQL Database:MySQL数据库服务器默认端口。
1.4、网络模型
OSI(Open System Interconnect),即开放式系统互联。 一般都叫OSI参考模型,OSI虽然提出了这个模型,但是一直没有实现,确实是比较复杂,后面美国国防部的高级研究计划局(ARPA)提出TCP/IP模型,只用了四层。
可以看到,有七层,五层,四层各种各样的协议,我们下面以五层为例,看看有哪些协议
物理层:RJ45、IEEE802.3 负责最后将信息编码成电流脉冲或其它信号用于网上传输
数据链路:VLAN、MAC 实现网卡接口的网络驱动程序
网络层:IP、ARP 实现数据包的选路和转发
传输层:TCP、UDP 提供主机之间数据传送服务
应用层:DNS、HTTP、WWW、FTP、SSH 、SMTP 提供用户接口,负责两个进程之间的信息交换。
会话层:建立、管理和终止会话
表示层:数据加密解密、压缩等
1.5、封装
上层协议通过封装使用下层协议的服务。应用程序数据在发送到物理网络上之前,将沿着协议栈从上往下依次传递。每层协议都将在上层数据的基础上加上自己的头部信息(有时还包括尾部信息),以实现该层的功能,这个过程就称为封装。
1.5.1、网络层封装
经过TCP封装后的数据称为TCP报文段(TCP message segment),或者简称TCP段。经过UDP封装后的数据称为UDP数据报(UDP datagram)。
TCP协议为通信双方维持一个连接,并且在内核中存储相关数据。这部分数据中的TCP头部信息和TCP内核缓冲区(发送缓冲区或接收缓冲区)数据一起构成了TCP报文段。向一个TCP连接写入数据时,内核中的TCP模块首先把这些数据复制到与该连接对应的TCP内核发送缓冲区中,然后TCP模块调用IP模块提供的服务。此时TCP协议为发送的数据保存了一份副本,等收到接收方的收到请求后,再释放这个副本。UDP则不同,UDP是不可靠的服务,当一个UDP数据报被成功发送之后,UDP内核缓冲区中的该数据报就被丢弃了。
1.5.2、传输层封装
经过IP封装后的数据称为IP数据报(IP datagram)。
1.5.3、数据链路层封装
经过数据链路层封装的数据称为帧(frame)。传输媒介不同,帧的类型也不同。比如,以太网上传输的是以太网帧(ethernet frame),而令牌环网络上传输的则是令牌环帧(token ring frame)。
1.6、分用
当帧到达目的主机时,将沿着协议栈自底向上依次传递。各层协议依次处理帧中本层负责的头部数据,以获取所需的信息,并最终将处理后的帧交给目标应用程序。这个过程称为分用(demultiplexing)。分用是依靠头部信息中的类型字段实现的。
二、TCP协议
TCP协议为应用层提供可靠的
、面向连接的
和基于流(stream)
的服务。TCP协议使用超时重传
、数据确认等方式来确保数据包被正确地发送至目的端,因此TCP服务是可靠的。TCP服务是基于流的。基于流的数据没有边界(长度)限制,它源源不断地从通信的一端流入另一端。发送端可以逐个字节地向数据流中写入数据,接收端也可以逐个字节地将它们读出。
2.1、TCP建立连接过程
2.1.1、三次握手
- 第一次握手:客户端发送SYN包(seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
- 第二次握手:服务器收到SYN包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
2.1.2、四次挥手
- 第一次挥手:主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,不会再发数据(在FIN包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),此时主动关闭方还可以接收数据。
- 第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。
- 第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,不会再发数据。
- 第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,完成四次挥手。
2.1.3、为什么需要三次握手
防止已经过期的连接再次到达主机。
如果A向B发送的连接信息没有到达,于是A重新发生一次,B收到并回应,建立了连接。数据交换完成之后,断开连接。如果这个时候,第一次发生的连接信息又到达了B,B就会以为A要建立连接,发送应答后就建立了新的连接,它会一直等待A发送数据。
2.1.4、为什么需要四次挥手
被动关闭方是否还有数据发送。FIN信号表示不再发送数据,如果被动关闭方没有数据发送,它也会发送FIN给对方。如果还有数据发送,就要等数据发送完之后才给对方发送FIN信号。
2.2、TCP的状态机模型
粗虚线表示典型的服务器端连接的状态转移;粗实线表示典型的客户端连接的状态转移;CLOSED是一个假想的起始点,并不是一个实际的状态。
2.2.1、服务端
- 服务端通过
listen
系统调用进入LISTEN
状态,等待客户端的连接 - 服务端监听到了客户端的连接请求(SYN帧),于是发一个
SYN&ACK
帧,将当前连接放入内核等待队列。此时改连接处于STN_RCVD
状态,等待客户端发ACK帧。 - 服务端收到
ACK
帧,则该连接转移到ESTABLISHED
状态。该状态是连接双方能够进行双向数据传输的状态。 - 服务端收到
FIN
帧,即客户端要求主动断开连接。服务器通过返回ACK
,使连接进入CLOSE_WAIT
状态。该状态的含义很明确:等待服务器应用程序关闭连接。 - 服务端发送
FIN
帧,即服务端准备结束,这将使连接进入LAST_ACK
状态,等到收到客户端的ACK
确认后,连接将被彻底关闭。
2.2.2、客户端
- 客户端通过
connect
系统调用进入SYN_SENT
状态, 主动与服务端建立联系,connect调用可能由于下面两个原因失败返回- connect连接的目标端口不存在(未被任何进程监听)
- connect在超时时间内未收到服务器的确认报文段
- 客户端收到了
SYN&ACK
帧,发送一个ACK
帧,则该连接转移到ESTABLISHED
状态,可以开始传递数据。 - 客户端主动关闭连接,先发送一个
FIN
帧,进入FIN_WAIT_1
状态- 如果只收到一个
ACK
,没有收到FIN
,则进入FIN_WAIT_2
状态,此时该连接可以收到数据,但是不能发送,相当于在等待服务端发送完数据,等到服务端发送完数据,发送了FIN
,客户端收到FIN
,发送ACK
则进入TIME_WAIT
状态 - 如果收到了
FIN
,则进入CLOSING
状态,此时客户端与服务端都要关闭连接,都在等待对方的ACK
帧,所以客户端发一个ACK
,等待收到服务端的ACK
就进入TIME_WAIT
状态 - 如果收到了
FIN&ACK
,相当于服务端也要结束连接,并且确认收到了,则客户端直接进入TIME_WAIT
状态
- 如果只收到一个
2.2.3、TIME_WAIT状态
主动关闭方发送最后一个ACK信号之后,会进入TIME_WAIT状态。保持一段时间后进入CLOSED状态。
2.2.3.1、MSL(最大分段生存期)
TCP报文在Internet上最长生存时间。每个具体的TCP实现都必须选择一个确定的MSL值。RFC 1122建议是2分钟,但BSD传统实现采用了30秒。TIME_WAIT 状态最大保持时间是2倍MSL,也就是1-4分钟。
2.2.3.2、存在原因
可靠关闭TCP连接
:TCP协议在关闭连接的四次挥手中,最后一次挥手的ACK帧是由主动关闭方发出的。如果这个帧丢失,被动关闭方将重新发送FIN帧。如果主动关闭方处于CLOSED 状态,就会响应RST(强制终止连接释放资源)而不是ACK。所以主动关闭方应该维持TIME_WAIT状态,再一次发送ACK。防止旧连接的数据重复到达
:TCP协议不允许处于TIME_WAIT状态的连接启动一个新的可用连接,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个新TCP连接的时候,来自旧连接重复分组已经在网络中消逝。
2.2.3.3、存在问题
TIME_WAIT状态是主动关闭方保存的状态。如果服务端有大量的连接处于TIME_WAIT状态,则说明是由服务端主动关闭连接的,而且服务端没有对TIME_WAIT状态的连接快速重用或回收。会导致占用系统的socket资源。
解决方法:
- 由客户端断开连接
- 服务端快速回收和重用处于TIME_WAIT状态的socket资源
2.3、TCP滑动窗口
每个主机都有一个发送缓存和接收缓存。同时每个主机都有一个发送窗口和一个接收窗口。
- 对于发送方,发送缓存中的
已发送但未收到确认
和未发送但允许发送
的这两部分组成发送窗口。 - 对于接收方,接收缓存中包括
已经按序到达但还未被处理的数据段
,以及已经接收到但未按序到达的数据段。
2.3.1、流量控制
就是让发送速率不要过快,让接收方来得及接收。利用滑动窗口机制就可以实施流量控制。发送方根据接收方接收窗口的大小来动态调整自己发送窗口的大小。如果接收方没有缓存可以用,发送窗口的就会设置为0,停止发送数据。
2.3.2、拥塞控制
发送方维持一个拥塞窗口,拥塞窗口的大小取决于网络的拥塞程度而动态变化。发送方让自己的发送窗口大小等于拥塞窗口的大小。同时还要设置一个慢开始门限。
拥塞窗口 > 慢开始门限,用慢开始
拥塞窗口 < 慢开始门限,改用拥塞避免
拥塞窗口 = 慢开始门限,都可使用
慢开始:主机开始发送数据时,并不清楚网络的负荷情况。因此,较好的方法是先探测一下,由小到大逐渐增大发送窗口。首先设置拥塞窗口为最大报文段长度,每次增加这个长度。
拥塞避免:让拥塞窗口缓慢地增大,每次只增加1,而不是加倍。拥塞窗口按线性规律缓慢增长,比慢开始算法的拥塞窗口增长速率缓慢得多。
慢开始和拥塞避免算法,当发送方判断网络出现拥塞(根据是否收到确认),将慢开始门限调整为发送窗口一半,拥塞窗口调整为1 。然后重新开始。
2.4、TCP的可靠性靠什么保证
- 确认和重传:TCP使用确认和重传机制来确保数据的可靠传输。接收端会发送确认消息,告知发送端已成功接收到数据。如果发送端在一定时间内没有收到确认消息,它会重新发送数据,直到接收到确认为止。
- 数据合理分片和排序:TCP链接会按照MTU最大传输单元分片,接收方会缓存未按序到达的数据,重新排序后交给应用层。UDP的数据报大于1500字节,大于MTU,在IP层需要被切片,接收方IP层则需要进行数据报的重组,一旦有一片丢失,就需要重新发送整个数据报。
- 数据校验:TCP报文头部有校验和,用于校验报文是否损坏
- 流量控制:接收方来不及处理发送方数据时,可以通过流量控制提示发送方降低发送速率,防止包丢失
- 拥塞控制:网络拥塞时,减少数据发送,防止包丢失
2.5、一些关于TCP的问题
2.5.1、服务器出现大量处于CLOSE_WAIT的连接
- 服务器内部业务处理占用了大量时间,没能来得及处理完业务执行close方法,或者业务逻辑有问题
- 服务器父进程派生子进程,子进程集成了socket,收到FIN时子进程处理但是父进程没有处理该信号,导师socket引用不为0无法回收。
修改程序bug
2.5.2、流量控制与拥塞控制的区别
- 流量控制由通信双方协商,拥塞控制由通信链路试探
- 流星控制需要通信双方各维护一个发送窗、一个接收窗,对任意一方,接收窗大小由自身决定,发送窗大小由接收方响应的TCP报文段中窗口值确定;拥塞控制的拥塞窗口大小变化由试探性发送一定数据量数据探查网络状况后而自适应调整。
- 最终发送窗口=min(流量控制窗口,拥塞窗口)
三、UDP协议
UDP协议为应用层提供不可靠
、无连接
和基于数据报
的服务。如果数据在中途丢失,或者目的端通过数据校验发现数据错误而将其丢弃,则UDP协议只是简单地通知应用程序发送失败。基于数据报的服务,是相对基于流的服务而言的。每个UDP数据报都有一个长度,接收端必须以该长度为最小单位将其所有内容一次性读出,否则数据将被截断。
3.1、TCP与UDP的区别
TCP提供面向连接的、可靠的数据流传输,而UDP提供的是非面向连接的、不可靠的数据流传输。
TCP基于流,UDP基于数据报。
TCP注重数据安全性,UDP数据传输快
TCP有拥塞控制,UDP没有,在一些场景这个特性很重要,比如电话会议
TCP连接是点到点的,UDP支持一对一,一对多,多对一,多对多
TCP首部开销20字节,UDP只有8字节
四、IP协议
4.1、MTU最大传输单元
如果发送的数据包大于MTU,则该数据包在传输过程中会被IP协议分片传输,使得每片数据报的长度小于MTU。分片传输的IP数据报不一定按序到达,但IP首部中的信息能让这些数据报片按序组装。
4.2、IPV4地址的分类
Class A(A类地址):以0开头的地址范围,范围从1.0.0.0到127.255.255.255。其中,第一个字节用于网络标识,剩余的三个字节用于主机标识。这种地址可以支持较大数量的主机,但网络数量较少。
Class B(B类地址):以10开头的地址范围,范围从128.0.0.0到191.255.255.255。其中,前两个字节用于网络标识,后两个字节用于主机标识。Class B地址可以支持中等数量的主机和网络。
Class C(C类地址):以110开头的地址范围,范围从192.0.0.0到223.255.255.255。其中,前三个字节用于网络标识,最后一个字节用于主机标识。Class C地址可以支持大量的网络,但每个网络只能支持较少的主机。
Class D(D类地址):以1110开头的地址范围,范围从224.0.0.0到239.255.255.255。Class D地址被用于多播(Multicast)通信,用于将数据包发送到多个目的地。
Class E(E类地址):以1111开头的地址范围,范围从240.0.0.0到255.255.255.255。Class E地址被保留未分配,用于将来可能的用途。
4.3、子网掩码
子网掩码是一种用于指示一个IP地址中哪些部分表示网络标识,哪些部分表示主机标识的32位二进制数。它与IP地址一起使用,用于划分一个网络中的主机和子网络。
子网掩码中的“1”表示对应IP地址的这一位是网络标识,而“0”表示这一位是主机标识。子网掩码的长度决定了网络标识和主机标识的划分位置。
例如,一个常见的子网掩码是255.255.255.0(或简写为/24),它指示前三个字节是网络标识,最后一个字节是主机标识。这意味着在这个网络中,前三个字节相同的IP地址属于同一个网络,而最后一个字节不同的IP地址则属于该网络中的不同主机或子网。
五、ARP协议
ARP协议能实现任意网络层地址到任意物理地址的转换,即从IP地址到以太网地址(MAC地址)的转换
。其工作原理是:主机保存了一份IP地址和MAC地址的映射高速缓存,先从表中查询,查询不到的话,主机向自己所在的网络广播一个ARP请求,该请求包含目标机器的网络地址。此网络上的其他机器都将收到这个请求,但只有被请求的目标机器会回应一个ARP应答,其中包含自己的物理地址。
Linux下可以使用arp命令来查看和修改ARP高速缓存。
# 查看
sudo arp -a
# 删除
sudo arp -d 192.168.189.2
# 添加
sudo arp -s 192.168.189.2 00:50:56:eb:2c:88
六、Http协议
6.1、请求三部分
- 请求行(Request Line):包括请求方法(GET、POST等)、请求的URL以及HTTP协议的版本号。
- 请求头部(Headers):包含了关于请求的各种信息,如用户代理、接受的内容类型等。
- 请求体(Request Body):在一些请求中,如POST请求,会包含请求发送的数据,比如表单数据或JSON数据等。
6.2、响应三部分
- 状态行(Status Line):包括HTTP协议的版本号、状态码以及对应的状态信息,例如 “HTTP/1.1 200 OK”。
- 响应头部(Headers):包含了响应的各种信息,如服务器类型、内容类型、响应时间等。
- 响应体(Response Body):包含了实际的响应内容,比如网页的HTML代码、图片、视频等。
6.3、常见HTTP请求
6.4、常见状态码
- 1xx-信息
- 100 目前为止,一切正常,可以忽略
- 2xx-成功
- 200 OK
- 3xx-重定向
- 301 永久性重定向
- 302 临时性重定向
- 4xx-客户端错误
- 400 请求报文有语法错误
- 401 发送的请求需要有认证信息,或用户认证失败
- 403 请求被拒绝
- 404 未找到相应资源
- 5xx-服务端错误
- 500 执行时发生错误
- 503 服务器超负荷,现在无法处理请求
6.5、HTTP与HTTPS的区别
- http数据以明文的方式在网络中传播,https传输的数据是通过加密的,安全性更高。
- https协议需要用到CA申请证书,需要支付一定费用
- https在tcp三次握手阶段之后,还需要进行ssl握手,协商加密使用的对称加密密钥
- http与https使用端口不一样前者80,后者443
6.6、HTTPS传输过程SSL过程
七、DNS协议
DNS是一套分布式的域名服务系统。每个DNS服务器上都存放着大量的机器名和IP地址的映射,并且是动态更新的。众多网络客户端程序都使用DNS协议来向DNS服务器查询目标主机的IP地址。
Linux使用/etc/resolv.conf
文件来存放DNS服务器的IP地址。
其中第一个选项为首选DNS,第二个为次选DNS。
Linux下一个常用的访问DNS服务器的客户端程序是host,比如下面的命令是向首选DNS服务器查询百度的IP地址:
host -t A www.baidu.com
host命令的输出告诉我们,机器名www.baidu.com是www.a.shifen.com.的别名,并且该机器名对应两个IP地址。
八、浏览器解析过程
-
在应用层,浏览器封装一个发送给web服务器的http请求
- HTTP请求由
请求行+消息报头+请求正文
组成
- HTTP请求由
-
在传输层,http请求被封装为TCP报文段
- TCP报文段需要设置端口,web服务器的HTTP端口默认是80,本机的端口是一个1024-65535之间的随机整数
- TCP报文段由
TCP首部+ HTTP数据包
组成。
-
在网络层,TCP报文段被封装为IP数据包
- 依次查找浏览器缓存、系统缓存、路由器缓存、ISP NDS缓存、根域名服务器。找到域名对应的IP地址
- IP数据包由
IP头部+TCP首部+HTTP数据包
组成
-
在网络接口层,IP数据包嵌入到数据帧(以太网数据包)
- 数据帧中包含源MAC地址和目的MAC地址,通过ARP地址解析协议得到的
- 数据帧由
头部(MAC地址)+IP头部+TCP首部+HTTP数据包
组成
最后的消息经过层层封装后: