传输层控制协议TCP简介:
- 面向连接的、可靠的基于字节流的传输层控制协议
- 将应用层的的数据流分割成报文段并发送给目标节点的TCP层
- 数据包都有序号(SEQ),对方收到则发送ACK确认,未收到则重传
- 使用校验和来校验数据在传输中,是否有误
进程间通信
(1)实际上TCP的发送方和接收方是进程间的通信,而单机线程间通信可以用PID,而多台机器间通信没有PID的概念,并且单机中PID唯一,容易造成冲突。而IP能唯一标识一台主机,而TCP的传输层协议的Source Port,和Destination Port定义了端口号,所以造成了IP+TCP协议+端口号,能唯一确认一台主机的一个线程。
(2)能够唯一标示网络中的进程后,它们就可以利用socket进行通信了,什么是socket呢?我们经常把socket翻译为套接字,socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。
socket通信系统模块示意图:
TCP报文头
上图中需要了解到的内容:
- Source Port:发送方端口号;Destionation Port: 接收方端口号
- Sequence Number (seq) :顺序号
- Acknowledgement Number(ack) :确认序号,只有ACK确认标志位为1时,ack才有效,ack = seq+1
- 标志位:共6个 URG、ACK、PSH、PST、SYN、FIN等
URG:紧急指针标志
ACK:确认序号标志
PSH:push标志
PST:重置连接标志
SYN:同步序号标志,用于建立连接过程
FIN:finish标志,用于释放连接
一、建立TCP连接的三次握手
为了来更好的理解TCP协议的连接过程,我们假设有此场景
A和B通话
A:“听得到吗”
B:“我听得到,你听到吗”
A:“听得到,我们可以说话了”
。。。正常通信内容(叭叭叭)
这样一段对话,来确保彼此能互相接收到消息。
对应到TCP的三次握手
- 一开始客户端和服务端都为CLOSE状态,等待一方发起建立连接过程,并且服务器放进入监听状态(LISTEN)。
- 第一次握手:客户端Client主动发送连接请求数据包,Client将同步标志SYN置为1,随机产生一个顺序号seq=x,此时Client为同步已发送状态(SYN-SENT),等待server确认。
- 第二次握手:服务端Server接收到数据包,如果同意建立连接,server将SYN和ACK都置为1,ack=x+1(一个SYN占一个字节号),随机产生一个顺序号seq=y,此时Server为同步已接收状态(SYN-RCVD)
- 第三次握手:Client收到确认数据包后,检验ack是否为x+1,ACK是否为1.如果校验成功将ACK置为1,ack=y+1,seq=x+1,发送给server。
- 如果正确则建立连接成功,Client和Server都进入ESTABLISHED状态,完成3次握手,随后Client和Server之间可以互相开始数据传输了。
一、终止TCP连接的四次挥手
- 由于TCP连接时是全双工的,所以每个方向都是可以主动发起终止连接的。并且发起终止连接前都是ESTABLISHED状态
- 第一次挥手,Client主动发送终止连接请求数据包,并且停止发送数据,将FIN标志位置为1,随机产生一个顺序号seq=u,Client进入FIN-WAIT-1终止等待状态
- 第二次挥手,Server收到终止连接请求后,发送一个ACK给Client,将ACK置为1,ack=u+1,随机产生一个顺序号seq=v,此时Server为CLOSE-WAIT关闭等待状态,Client进入FIN-WAIT-2状态。注:此时j进入半关闭状态,Client不发送数据了,但是Server还能接收到数据
- 第三次挥手,Servert持续接收数据一段时间后,发起FIN请求数据包,并将ACK置为1,ack=u+1,随机产生一个顺序号seq=w.Server进入LAST-ACK状态
- 第四次挥手,Clinet接收到Server的终止请求FIN后,确认ACK为1并且ack=u+1之后,CLIENT进入TIME-WAIT状态,接着发送一个ACK请求给server,ack=w+1,seq=u+1.此时Server进入CLOES状态
常见问题:
1.为什么建立连接要3次握手,而断开连接要四次挥手?
答:这是因为Server在LISTEN状态下,在收到Client的SYN数据包后,可以将SYN和ACK一同发送给Client。
而在断开连接时,Client发送一个FIN数据包,仅仅代表着Client不再发送数据,而Server还能继续接收数据,
所以FIN请求和ACK请求一般是分开发送的,也就造成了4次挥手。
2.为什么再第四次挥手后Client没有马上进入CLOSE状态,而需要等待2MSL
答:(1)确保Server有足够的时间接收到ACK包。如果Server没有收到ACK,需要SERVERC重发FIN包,CLIENT再发一次ACK,正好2MSL
(2)避免新旧连接混淆。