TCP/IP报文

IP协议: 无连接 , 不可靠 ,无状态

IPv4报头结构 IP数据报 = IP报头 + 传输层传递的数据
TCP/IP报文
4位版本号 : IP协议版本
4位头部长度 : 最大为1111 >> 15 个四字节 = 60
8位服务类型 : 3位优先权字段忽略 最小延时 最大吞吐量 最高可靠 最小费用 4位是互斥的 一位保留
16位标识 : 3位标志 13位偏移量

  • 3位标志 第一位保留 第二位表示禁止分片DF(do not fragment) 第三位表示有更多的分片MF(more fragment)[除了最后一个分片外,其他分片必须设置为1]
  • 13位偏移量 每个数据报第一个字节相对于原始数据的偏移值(每个分片的大小必须是8的倍数,保证了偏移值最低三个都是0)[13 位表示16位的偏移值]
    TTL (time to live): [最大为255] 数据报在网络中最多经过的路由器的个数,每经过一个路由器TTL减1
    **协议8bite ????*这个字段指示IP下一步应当把这个数据包发往更高层的协议,如TCP为6,UDP为17。

传输层

TCP协议 : 面向连接的 可靠的 字节流服务
UDP协议 : 无连接 不可靠 数据报服务

UDP协议报头:

十六位源端端口号 十六位目的端端口号
十六位UDP包长度 十六位头部校验和
数据报服务
TCP/IP报文数据报服务
如果接收端一次recvfrom没有将一个UDP数据报的数据部分读取完成,则剩余的数据会被丢弃掉.
字节流服务
TCP/IP报文字节流服务
应用层发送端send的次数与接受端recv的次数没有关系
发送端send的次数与网络底层封装的TCP报文段个数也没有关系
接受方接受数据时,如果一次未将数据接受缓冲区中的数据读取完成,剩余的数据会保留在缓冲区中.

字节流服务可能出现的粘包问题
粘包出现的原因:

  1. 发送端需要等缓冲区满才发送出去,造成粘包
  2. 接收方不及时接收缓冲区的包,造成多个包接收

解决方案

  1. 发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。
  2. 发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。
  3. 可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。等等。
什么是面向连接 ?
面向连接
  1. 两端通信之前必须建立一条通讯信道
  2. 通信结束后必须关闭信道以释放资源
  3. 通讯过程,要维护连接,两端内核必须分配资源(心跳包机制[判断信道是否可用])
  4. 保证数据传输的可靠性
  5. 同步通信双方TCP报文段的标识[保证是对方发送的(安全问题)]
为什么三次握手??两次行不行

防止客户端进行SYN溢出攻击, SYN溢出攻击,客户端不断发送SYN会不断消耗服务器资源.

三次握手过程

TCP/IP报文

四次挥手过程

TCP/IP报文
为什么要四次挥手?
TCP/IP报文
TCP是全双工模式,这就意味着,当 Client 发出FIN报文段时,只是表示 Client 已经没有数据要发送了,Client 告诉 Server,它的数据已经全部发送完毕了;但是,这个时候 Client 还是可以接受来自 Server 的数据;当 Server 返回ACK报文段时,表示它已经知道 Client 没有数据发送了,但是 Server 还是可以发送数据到 Client 的;当 Server 也发送了FIN报文段时,这个时候就表示 Server 也没有数据要发送了,就会告诉 Client ,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。

TIME_WAIT存在的意义: 2*MSL
  1. 保证迟来的数据能被识别并丢弃
  2. 保证可靠的终止TCP连接
服务器有大量的链接处于CLOSE_WAIT状态?

主要原因是某种情况下对方关闭了socket链接,但是我方忙与读或者写,没有关闭连接。
解决方案:
基本的思想就是要检测出对方已经关闭的socket,然后关闭它。

TCP头部结构

TCP/IP报文