OSI七层模型、TCP/IP四层模型
OSI七层模型
开放式系统互联(Open System Interconnect,OSI)定义了网络互连的七层框架(物理层、数据链路层、网络层、传输层、会话层、表示层、应用层),即ISO开放互连系统参考模型。
<mark>每一层实现各自的功能和协议,并完成与相邻层的接口通信。</mark>
TCP/IP四层模型
OSI参考模型
是学术上和法律上的国际标准,是完整的权威的网络参考模型。
TCP/IP参考模型
是事实上的国际标准,即现实生活中被广泛使用的网络参考模型。
对比 OSI、TCP/IP
(简图)
OSI七层网络模型 | TCP/IP四层概念模型 | 对应网络协议 |
应用层(Application) | 应用层 | HTTP, TFTP, FTP, NFS, WAIS、 SMTP |
表示层(Presentation) | Telnet, Rlogin, SNMP, Gopher | |
会话层(Session) | SMTP, DNS | |
传输层(Transport) | 传输层 | 进程和端口 TCP, UDP, DCCP, SCTP, RTP, RSVP 数据的单位成为数据段 (Segment) |
网络层(Network layer) | 网络层 | 路由器,防火墙 IP, ICMP, ARP, RARP, AKP, UUCP 数据的单位称为数据包(packet) |
数据链路层(Data Link Layer) | 数据链路层 | 网桥,交换机 FDDI, Ethernet, Arpanet, PDN, SLIP, PPP 数据的单位称为帧(frame) |
物理层(Physical Layer) | 网卡,网线,集线器,中继器,调制解调器 IEEE 802.1A, IEEE 802.2到IEEE 802.11 数据的单位称为比特(bit) |
(全面)
TCP协议
(TCP报文结构)
# 三次握手
(流程图)
-
客户端
发送连接请求报文段
<mark>将同步序号(Synchronize Sequence Numbers,SYN)标识设为1
将序号(Sequence Number,seq)置为x</mark>(x为随机产生的一个值)
然后进入SYN_SEND状态
(同步发送状态)
-
服务器
收到SYN报文段进行确认
<mark>将SYN标识位置为1</mark>
<mark>确认序号(Acknowledgment Number,ACK)标识置为1</mark>
(当ACK=1时,确认字段才有效。当ACK=0时,确认号无效。)
<mark>序号(Sequence Number,seq)置为y</mark>(y为随机产生的一个值)
<mark>确认序号(Acknowledgment Number,ack)置为x+1</mark>
然后进入SYN_RECV状态
(同步接收状态,半连接状态)
-
客户端
再进行一次确认
<mark>确认序号(Acknowledgment Number,ACK)标识置为1(此时不用SYN)
确认序号(Acknowledgment Number,ack)置为y+1
序号(Sequence Number,seq)置为x+1</mark>(此时不用SYN)
发向服务器
最后客户端与服务器都进入ESTABLISHED 状态
(建立连接状态)
为什么在第3步中客户端还要再进行一次确认呢?
这主要是为了防止已经失效的连接请求报文段突然又传回到服务端而产生错误的场景:
.
- 所谓"已失效的连接请求报文段"是这样产生的。
正常来说,客户端发出连接请求,但因为连接请求报文丢失而未收到确认。
于是客户端再次发出一次连接请求,后来收到了确认,建立了连接。
数据传输完毕后,释放了连接,客户端一共发送了两个连接请求报文段,其中第一个丢失,第二个到达了服务端,没有"已失效的连接请求报文段"。
.- 现在假定一种异常情况,即客户端发出的第一个连接请求报文段并没有丢失,只是在某些网络节点长时间滞留了,以至于延误到连接释放以后的某个时间点才到达服务端。本来这个连接请求已经失效了,但是服务端收到此失效的连接请求报文段后,就误认为这是客户端又发出了一次新的连接请求。于是服务端又向客户端发出请求报文段,同意建立连接。假定不采用三次握手,那么只要服务端发出确认,连接就建立了。
.- 由于现在客户端并没有发出连接建立的请求,因此不会理会服务端的确认,也不会向服务端发送数据,但是服务端却以为新的传输连接已经建立了,并一直等待客户端发来数据,这样服务端的许多资源就这样白白浪费了。
.采用三次握手的办法可以防止上述现象的发生。比如在上述的场景下,客户端不向服务端的发出确认请求,服务端由于收不到确认,就知道客户端并没有要求建立连接。
# 四次分手
当客户端没有数据再需要发送给服务端时,就需要释放客户端的连接,这整个过程为:
-
客户端
发送一个报文给服务端(没有数据)
<mark>其中FIN设置为1
序号(Sequence Number,seq)置为u</mark>(随机)
客户端进入FIN_WAIT_1状态
-
服务端
收到来自客户端的请求(会做两件事)
-
发送一个ACK给客户端
<mark>ACK置为1
确认序号(Acknowledgment Number,ACK)置为u+1
Sequence Number为v</mark>
服务端年进入CLOSE_WAIT状态
(等待关闭连接状态)
-
发送一个FIN给客户端
<mark>FIN置为1
ACK置为1
Sequence置为w
Acknowledge置为u+1</mark>
用来关闭服务端到客户端的数据传送
服务端进入LAST_ACK状态
(最后一次确认状态)
客户端
收到FIN后,进入TIME_WAIT状态
<mark>接着发送一个ACK给服务端
Acknowledge置为w+1
Sequence Number置为u+1</mark>
最后客户端和服务端都进入CLOSED状态
# Wireshark 分析数据传输过程
参考:Understanding TCP Sequence and Acknowledgment Numbers(扶墙)
看有什么时候有时间,或者看哪位大大把它翻译过来把