跳到主要内容

TCP 协议

模型详解

iso 标准

tcp_model

iso标准 应用层、表示层和会话层合并为应用层。在TCP协议中为一层

所以就为: 应用层 -> 传输层 -> 网络层 -> 数据链路层 -> 物理层

OSI中的层功能TCP/IP协议族
应用层文件传输,电子邮件,文件服务,虚拟在终端TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet
表示层数据格式化,代码转换,数据加密没有协议
会话层解除或建立与接的节点的联系没有协议
传输层提供端对端的接口TCP,UDP
网络层为数据包选择路由IP,ICMP,RIP,OSPF,BGP,IGMP
数据链路层传输有地址的帧一级错误检测功能SLIP,CSLIP,PPP,ARP,RARP,MTU
物理层以二进制数据形式在屋里媒体上传输数据ISO2110,IEEE802,IEEE802.2

流程

发起请求

url -> 添加请求头等包装 -> tcp协议进行打包 -> 继续打包 ...

接受请求

逐条解压 ...-> 只留数据

应用层

传输层之上,便是应用层。传输层的UDP报文和TCP报文段的数据部分就是应用层交付的数据,不同类型的网络应用有不同的通信规则,

因此应用层协议是多种多样的,比如 DNS、FTP、Telnet、SMTP、HTTP、RIP、NFS 等协议都是用于解决其各自的一类问题。

传输层

网络接口:套接字

TCP

  • 有连接:需要用端口号建立连接

  • 可靠传输:发送者能感知到是否发送成功

  • 面向字节流:字节流读取数据

TCP最核心的机制

  • 可靠传输

  • 尽可能提高传输效率

可靠性传输 发送者能感知到失败(对比打电话和发短信)

面向字节流,文件操作(I/O流)

UDP

  • 无连接: 知道对端的IP的端口号就可以直接传输,不需要建立连接

  • 不可靠: 没有确认机制,没有重传机制,如果因为网络故障该段无法发送到对端,UDP协议也不会给应用层返回任何错误信息

  • 面向数据报: 不能灵活的控制读写数据的次数和数量

网络层

网络层用来处理在网络上流动的数据包。数据包是网络传输的最小数 据单位。该层规定了通过怎样的路径(所谓的传输路线)到达对方计算机,并把数据包传送给对方。

与对方计算机之间通过多台计算机或网络设备进行传输时,网络层所 起的作用就是在众多的选项内选择一条传输路线。

网络接口:原始套接字(必须要提供权限)

数据链路层

处理设备连接

详细资料请参考 TCP/IP--数据链路层

物理层

硬件相关

TCP 封装结构

tcp_info

  1. 端口,端口分发送端的端口(源端口source port) 和 接收端的端口(目的端口Destination port),为什么要这两个端口。因为要分辨这处理数据的进程是谁,只能通过端口去分辨进程。
  2. 数据号Sequence Number,它是一个4字节的数据。TCP在给数据打包传送到下一层时不可能把所有的数据都打成一个大包,因为效率很低。它要把这个数据分成若干小包,逐个小包去进行分装,这些小包是有顺序的,这些数据就由数据号去体现。对方收到小包要组装,按照数据号来组装。这是为了减少重传的时候减少消耗,哪些失败了或者丢包了就重传哪个,不至于整个都重传。
  3. 应答号Ackonwledgment Number,给对方的排序依据,上边的是给自己排序的依据。这样一来一回数据不会乱。这样就直接能对应上哪个编号的包失败了或者丢失了,就看应答号哪个没有对上。 后边还有一些偏移量Offset,标志位,滑动窗口,校验,处理指针,附加选项等等

三次握手 & 四次挥手

tcp_connection

三次握手

建立连接时候的三次通信过程

  1. 客户端发起连接指令状态SYC_SENT,它会发一个连接请求包过去,然后指令会携带一个数据号,seq = x。

  2. 服务器一开始是监听状态,收到包以后状态就变成了SYN_RCVD状态,就是开始握手了。服务器收到请求连接包以后它要发两个指令,发起连接指令和应答连接指令,合并在一起发过去,为了节省操作次数。SYN seq = y,ACK = x + 1。为什么服务器也要发送连接请求指令?因为TCP是双向连接,只连一遍叫半连接。y是服务器的数据号,x是客户端的数据号。为什么服务器要在客户端的数据号+1?因为这样客户端就知道下一个要发的数据号是多少,而且中间也不会发生跳号,这也叫应答号。如果中间某一个数据号服务器没有应答回来,那代表它丢失了或者失败了,客户端需要重新发送的。

  3. 此时客户端的状态是ESTABLISHED, 此时客户端会检查服务端是不是收到了正确的数据号,第二件事处理服务器发来的连接请求。这个时候客户端知道服务器是可以连接的状态,但是服务器不知道客户端是不是可以连接的状态,这个时候是半连接。客户端这个时候需要发送应答指令给服务器,ACK = y + 1。这样服务器也就知道了客户端也是可连接的状态,服务器的状态也会改编成ESTABLISHED,这样就建立了双向连接。

用个小故事说明

约人出来撸串为例

A(客户端) B(服务端)

  1. A 给 B 发了一个消息(SYC_SENT),出来撸串吗?(seq = x)
  2. B 收到了消息(状态就变成了 SYN_RCVD), 发送给 A 说可以(seq = y, ack = x + 1)
  3. A 收到了消息,并且回复了说可以(ACK = y + 1),然后就到了约定的时候一起出去撸串了,后续如何,看下边

四次挥手

断开连接时候的四次通信过程。在正常情况下断开也需要客户端发起,非正常情况下服务器也会断开。当建立好TCP连接之后会有一些维持连接的命令,如果一段时间服务器没有收到在线检测包或者数据包,它会认为客户端超时,服务端会主动断开连接。服务端断开也会告知客户端,客户端收到断开请求以后它要响应客户端,告诉客户端收到断开请求了。当客户端第一次收到断开请求之后,就不能再发送有效数据了。但是仍然可以发送指令的。

  1. 客户端发送断开指令

  2. 服务器发送一个响应

  3. 服务器再发一个断开指令, 为什么要分开发送指令跟响应,因为有可能服务器还有没发送完的数据,所以要等数据发完才可以发送断开指令。这就好比你说我要挂电话了,对方说好我知道了,但是你先等我把话说完。等对方说完之后,对方给你说,好我说完了可以挂电话了。

  4. 客户端发送应答,此时就完全断开连接,想要发送数据只能重新建立连接。

用个小故事说明

约人出来撸串散场了

A(客户端) B(服务端)

  1. A 给 B 说我去结账,我们撤吧。
  2. B 说可以,让我吃完
  3. B 吃完了说,走吧,买单
  4. A 说好,这场聚会就散了,什么时候在聚会,可能要下次在预约了

查看TCP连接状态

shell 中输入,命令更多参数参考 netstat

netstat -an

会有一个state的状态值