昨天学习了网络中的OSI模型,但OSI模型并没有被广泛应用,反而TCP/IP模型获得了较大的成功,那今天就来学习下TCP/IP模型。
开始疯狂的十万个为什么
什么是TCP/IP模型?
TCP/IP参考模型是美国国防部高级研究计划局计算机网(Advanced Research Projects Agency Network,ARPANET)和其后继因特网使用的参考模型。ARPANET是由美国国防部(U.S.Department of Defense,DoD)赞助的研究网络。
最初,它只连接了美国境内的四所大学。随后的几年中,它通过租用的电话线连接了数百所大学和政府部门。最终ARPANET发展成为全球规模最大的互连网络-因特网。
我是这么记得:美国国防部搞得网络模型---发展壮大----最后发展成了因特网
既然叫TCP/IP模型,什么是TCP和IP?
TCP和IP分别是两个协议
TCP:传输控制协议
IP:互联网协议地址(Internet Protocol Address),缩写就是IP地址
细节我们等等再说。
现在我大概知道TCP/IP是怎么来的了。来看看它的结构模型。
TCP/IP模型的体系结构
TCP/IP的参考模型将协议分成四个层次。对比OSI模型如图:
可以看到TCP/IP模型把OSI模型浓缩了一些,没有OSI模型那么详细。
应用层
表示层 ----- 应用层
会话层
这三层合并为应用层:为用户提供各种服务。例如:HTTP,HTTPS,TFP,Telnet
TCP/IP中的传输层 ----- OSI中的传输层
提供了端对端的通信连接方式,可靠的连接方式:TCP,不可靠的连接方式:UDP
TCP/IP中的网络层 ----- OSI中的网络层
提供主机与主机间的通信,并找到一条好的路径
网络接口层 ----- OSI中的链路层,物理层
负责监视主机在和网络之间的交换
现在来比较下他们的相同点和不同点
相同点:
1.都采用了层级化结构
2.都提供了无连接和面向连接两种通信服务机制
不同点:
1.TCP/IP模型是四层结构,ISO是七层结构
2.TCP是根据协议才制定的模型,而ISO模型是协议开发前就设定的,具有通用性。
接下来学习下TCP的连接和断开
TCP连接的建立(三次握手)
首先要认识几个标志位和序号:
SYN:表示建立连接
ACK:表示确认序号有效
FIN:表示关闭连接
RST:表示连接重置
PSH:表示有 DATA数据传输
发送报文时,带上相应的标志位,就代表相应的意思
1.seq序号,占32位,发起方发送数据时进行标记。
2.ack序号,确认序号,占32位。
例如:
- SYN=1,代表建立连接
- SYN=1,和ACK=1,就代表建立连接和确认序号有效。
- ACK=1,代表确认序号有效
第一次握手:客户端A向服务器B发送请求报文
请求报文是这样的
1.标志符:SYN=1,代表建立连接
2.随机初始化的一个序号:比如seq=x.
客户端A进入(SYN-SEND)同步已发送状态。
第二次握手:服务器B收到后,如果同意连接,那么服务器B就会向客户端A发送一个确认报文。
确认报文是这样的
1.标志符:ACK=1,表示对刚刚的SYN包的确认,SYN=1,表示B与A建立连接。
2.随机初始化一个序号:比如seq=y.
3.确认序号ack:ack是刚刚客户端A发送过来的序号+1,也就是x+1。
服务器B进入SYN-RCVD(同步收到)状态
第三次握手:客户端A收到服务器B的确认报文后,再向服务器B发送一个确认报文。
这个确认报文是这样的:
1.标志符:ACK=1,表示对刚刚的SYN包的确认。
2.seq是上个请求的序号+1,也就是x+1
3.确认序号ack:ack是刚刚客户端B发送过来的序号+1,也就是y+1.
客户端和服务器进入ESTABLISHED(TCP连接成功)状态。
单纯看标志符就是这样一个过程:
- (A) –> [SYN] –> (B)
- (B) -> [SYN/ACK] -> (A)
- (A) –> [ACK] –> (B)
看序号的话就是这样的
方向 seq ack
A->B 2000 0
B->A 3000 2001
A->B 2001 3001
A随机初始化了一个序号seq=2000
B随机初始化了一个序号seq=3000
A在接着上一个请求继续下去,seq=20001。
服务器B收到后确认seq值和ACK,说明连接建立成功。
TCP连接的断开(四次挥手)
假设客户端A想要断开连接
第一次挥手:
客户端发送一个 FIN 标志位为1的包,表示自己已经没有数据可以发送了,但是仍然可以接受数据。
发送完毕后,客户端进入 FIN_WAIT_1 状态。
第二次挥手:
服务器B确认客户端A发送的 FIN 包,发送一个确认包,表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接。
发送完毕后,服务器端进入 CLOSE_WAIT 状态.
客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态,等待服务器端关闭连接。
第三次挥手:
服务器端准备好关闭连接时,向客户端发送FIN 为1的结束连接请求。
发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个ACK。
第四次挥手:
- 客户端:接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT状态。等待可能出现的要求重传的 ACK 包。
- 服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。
- 客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。
形象点说就像这样
A说:"我说完了。" A进去FIN-WAIT-1状态。
B说:"我知道你说完了,但我还没说完啊,我还没准备好,让我等会。"
于是呢A进入了FIN-WAIT-2状态,B进去了CLOSE-WAIT状态
B说:"我讲完了,我也不说了"于是B进去了LAST-ACK状态。
A说:"好了,我知道你不说了"于是A进去了TIME-WAIT状态。B进去了CLOSED状态
最后A在等了一会,发现B没有理他,于是认为B不说话了,自己也不说了。A进去了CLOSED状态。
为什么连接的时候是三次握手,关闭的时候却是四次挥手?
不同地方就在于:。
关闭连接时,是分别发送ACK包和FIN包的。
建立连接时,SYN包和ACK包可以一起发送。
这样的原因是因为:关闭连接时,可能客户端A还在发送报文,只能告诉客户端,我已经收到了。直到客户端A发送完报文时,服务器B才可以发送FIN报文。
参考文章:
https://blog.csdn.net/ygm_linux/article/details/79546034
https://blog.csdn.net/diligentkong/article/details/73351278
http://www.imooc.com/article/19345