【Linux网络编程】传输层协议(1)--TCP/UDP--原理

目录

前言:

UDP协议

UDP协议的特征 

UDP协议端格式

UDP的缓冲区

分离与交付(封装与解包)

UDP的注意事项 

TCP协议 

 TCP协议段格式

确认应答机制(ACK) 

捎带应答机制 

超时重传机制

连接管理机制 

建立连接/三次握手简介

断开连接/四次挥手简介

详谈三次握手 

详谈四次挥手 


前言:

传输层主要负责数据能够从发送端传输接收端,在socket编程中我们写的套接字就是传输层中的协议

常见的传输层协议有两个:

  • UDP协议
  • TCP协议

这两个协议中有相同的特征,如下:

  • UDP和TCP都需要通过IP地址和端口号标识互联网中的一个进程
  • UDP和TCP在进行数据传输时,它们都是全双工的

注意:全双工指的是通信过程中数据可以在两个方向上同时传输,即实现信号的双向同时传输(A→B且B→A)

支持全双工的原因是内核的传输层中维护了两个缓冲区,发送缓冲区和接收缓冲区。这两个缓冲区互不影响!这一点在应用层中详细说明过

  • 图中,主机A从发送缓冲区中拿取数据发送给主机B的同时,主机B也可以从自己的发送缓冲区中拿取数据发送给主机A,这两个步骤是不会相互影响的! 

端口号与进程的关系 

一个进程可以bind多个端口号

  • 实际上,我们需要的是客户端可以使用ip地址和端口号唯一标识一个进程,而反过来成不成立都可以 

一个端口号不可以被多个进程bind 

实际上,我们要使用UDP/TCP时server都需要手动进行bind

一般地、内核中维护了一个端口号和PCB之间的kv结构,所以我们bind的时候是把这个端口号和进程PCB之间构建好映射以后,插入到哈希表之类的数据结构中!就能很快的根据端口号找到对应进程        


UDP协议


UDP协议的特征 

  • 无连接
  • 不可靠
  • 面向数据报 

无连接主要说明UDP的通信就像是寄信一样,你写好了一封信以后不需要经过收信人的同意可以直接送到他家去。UDP在发送数据之前不需要建立连接。发送方可以随时随地发送数据,接收方也无需事先同意接收。这种特性使得UDP的通信过程更加简单、高效,但同时也意味着UDP不提供像TCP那样的可靠传输机制。

网络传输的过程中是可能会丢包的,即传输过去的数据对方接收不到,如果是使用UDP进行传输,那么发生丢包什么都不管,这也是说明UDP是不可靠的原因!不可靠仅仅是UDP的特征,不是它有BUG。正因为它不需要保证数据的可靠,所以它才能简单、高效。TCP是可靠的,但TCP的可靠是付出了很多代价的

应用层交给UDP多长的报文, UDP原样发送, 既不会拆分, 也不会合并。假设用UDP传输100个字节的数据,如果发送端调用一次sendto, 发送100个字节, 那么接收端也必须调用对应的 一次 recvfrom, 接收100个字节; 而不能循环调用10次recvfrom, 每次接收10个字节。总得来说,面向字节流比起面向数据报更加灵活一些

UDP协议端格式

  • 图中除了数据以外的所有字段,它们共同组成了UDP通信时的传输层报头
  • 数据实际上就是有效载荷
  • UDP是可以进行双向通信的,它的传输层报头中包含了源端口和目的端口,这样就可以确定把数据交到哪个应用层进程

实际上,所谓的协议,也就是一个双方都定义出来的结构化的数据,在内核中UDP的协议的伪代码如下:

struct XXX
{
    uint16_t src_port;//源端口
    uint16_t dst_port;//目的端口
    uint16_t udp_len;//UDP长度
    uint16_t check;//校验和
};
  • 这个结构体被定义在通信双方OS内核中。协议就是结构体,这就是大多数协议的本质,不仅仅UDP

UDP中有两个字段是相对陌生的:

  • 16位UDP长度
  • 16位UDP校验和

尽管UDP本身是一个无连接的、不可靠的传输协议,但校验和机制为数据传输提供了一定程度的可靠性保障。通过检测并丢弃可能损坏的数据报,校验和有助于减少上层协议接收到错误数据的可能性。

UDP长度表示的是报头+有效载荷的长度,其中报头的大小是固定的8字节

UDP长度 = 有效载荷长度 + 8

正因为UDP长度的存在,提供给UDP面向数据报的能力


UDP的缓冲区

  • 发送缓冲区存在的意义是发送方可以进行等待接收方,当接收方速度过慢时,先把数据放入发送缓冲区作为缓冲 
  • 由于UDP不需要保证数据可靠性,所以对于UDP来说不需要内核中的发送缓冲区,因为我根本不需要临时保存数据,不需要管对方是啥状态!sendto直接拷贝数据给OS即可
  • UDP具有接收缓冲区. 但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致; 如果缓冲区满了, 再到达的UDP数据就会被丢弃;

分离与交付(封装与解包)

UDP的分离:实际上根据UDP长度即可得到有效载荷的长度,就能把UDP报头进行封装/分离

UDP的交付:根据目的端口即可知道交付给哪个进程 


系统角度理解封装和解包

  • 实际上,报文的传输并不是互斥的,即主机A向主机B发送报文时可能还存在主机C也同时在发送报文给主机B。 
  • OS内可以同时存在很多个收到的报文,这个报文还没来得及处理,这个报文可能只到了接收缓冲区甚至是网络/链路层
  • 由于OS内可能存在大量的还没来得及处理的报文,所以OS需要对这些大量的报文进行管理
  • OS对报文的管理方式就是先描述、后组织。

所以OS内一定存在着一个描述报文的内核结构体,这个结构体叫做sk_buffer。并且也一定会给报文提供内存空间!

示例图:

  • 图中,对报文的管理就变为了对链表的增删查改 

封装:所谓的封装就是给报文添加上对应层的报头

  • 所谓的封装报头就是把sk_buffer中的head指针左移,左移的字节数要看封装的是什么报头。不管封装的是什么报头,它都是结构体类型,都能sizeof算出它的大小
  • 通过head指针填完对应报头的信息

 解包:所谓的解包就是对报文去掉对应层的报头

  • 所谓的解包就是sk_buffer中的head指针右移,右移的字节数要看封装的是什么报头。
  • 指针右移完以后交付给上层就完成了一层解包

所以所谓的封装和解包,在内核中只需要进行指针移动即可控制 


UDP的注意事项 

在UDP报头中,UDP长度是用16位的一个整形来存储的,换句话来说,你发送的数据的字节数不能超过这个整形能表示的字节数,这个整形能表示64KB。若你一次发送的数据超过64KB,那么就需要在发送方应用层手动分包进行分批发送!分批发送完以后接收方再把收到的数据手动拼接起来 


TCP协议 


 TCP协议段格式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值