传输层

负责数据能够从发送端传输接收端.

再谈端⼝号

端⼝号(Port)标识了⼀个主机上进⾏通信的不同的应⽤程序;

在TCP/IP协议中,⽤"源IP","源端⼝号","⽬的IP","⽬的端⼝号","协议号"这样⼀个五元组来标识⼀个 通信(可以通过netstat-n查看);

端⼝号范围划分

• 0-1023:知名端⼝号,HTTP,FTP,SSH等这些⼴为使⽤的应⽤层协议,他们的端⼝号都是固定的.

• 1024-65535:操作系统动态分配的端⼝号.客⼾端程序的端⼝号,就是由操作系统从这个范围分配 的.

认识知名端⼝号

有些服务器是⾮常常⽤的,为了使⽤⽅便,⼈们约定⼀些常⽤的服务器,都是⽤以下这些固定的端⼝号: • ssh服务器,使⽤22端⼝

• ftp服务器,使⽤21端⼝

• telnet服务器,使⽤23端⼝

• http服务器,使⽤80端⼝

• https服务器,使⽤443

执⾏下⾯的命令,可以看到知名端⼝号

cat /etc/services

我们⾃⼰写⼀个程序使⽤端⼝号时,要避开这些知名端⼝号.

两个问题

1. ⼀个进程是否可以bind多个端⼝号?

可以。 一个进程能创建多个独立的 Socket,每个 Socket 分别调用bind()绑定不同的端口,就能实现单进程监听多个端口。

2. ⼀个端⼝号是否可以被多个进程bind?

默认不可以;特殊配置下可行。 默认系统会限制端口独占绑定,一个端口被进程绑定后,其他进程无法再绑定; 给 Socket 设置SO_REUSEADDR/SO_REUSEPORT套接字选项、满足对应约束后,多个进程可以绑定同一个端口。

UDP协议

UDP协议端格式

源端口:发送进程绑定的端口,用于回复。可为 0(表示不需要回复)。

目的端口:接收进程的端口,是 UDP 实现多路分用的唯一核心依据。

长度:整个 UDP 数据报的长度(头部+数据),最小为 8(即无数据)。

校验和:覆盖 UDP 头部、数据和从 IP 层提取的部分信息(伪首部),用于差错检测。在 IPv4 中可选(可全为 0 表示不校验),IPv6 中则强制计算。

UDP的特点

UDP传输的过程类似于寄信.

  • 无连接:传输前无需建立连接(无三次握手),发完也无需释放连接,启动快、延迟低。
  • 不可靠交付:不保证数据一定送达、不保证顺序、不做重传和拥塞控制,丢包不补救。
  • 面向报文:对应用层的报文直接封装,不拆分、不合并,一次发送一个完整报文。
  • 头部开销极小:固定 8 字节报头,远小于 TCP,传输额外成本低。
  • 支持多模式通信:除了一对一,还支持广播、多播(一对多、多对多),适合直播、语音、实时游戏等场景

⾯向数据报

应⽤层交给UDP多⻓的报⽂,UDP原样发送,既不会拆分,也不会合并;

⽤UDP传输100个字节的数据:

• 如果发送端调⽤⼀次sendto,发送100个字节,那么接收端也必须调⽤对应的⼀次recvfrom,接收 100个字节;⽽不能循环调⽤10次recvfrom,每次接收10个字节;

UDP的缓冲区

与 TCP 那种“字节流缓存”不同,UDP 的缓冲区完全是另一套逻辑,直接体现了它无连接、不可靠的本质。

• UDP没有真正意义上的发送缓冲区.调⽤sendto会直接交给内核,由内核将数据传给⽹络层协议进 ⾏后续的传输动作;

• 那通过 SO_SNDBUF 设置的“发送缓冲区”是什么?它本质上是一个限制单套接字在“发送途中”占用内核内存总量的配额。

作用机制:当数据报提交给 IP 层到网卡硬件真正完成发送之间,会短暂占用内核内存(如排队在流量控制 qdisc 中)。如果应用发得过快,占用内存会持续增长。一旦“在途”内存总量超过该配额:

• 阻塞套接字:sendto 会阻塞,直到内存释放。

• 非阻塞套接字:立即返回 EAGAIN / EWOULDBLOCK 错误。

• 实质:它为无节制的 UDP 发送提供了一个本地的“背压”机制,防止一个进程耗尽所有内核内存。

• UDP具有接收缓冲区.但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序⼀ 致;如果缓冲区满了,再到达的UDP数据就会被丢弃;

UDP的socket既能读,也能写,这个概念叫做全双⼯.

总结

TCP有发送缓冲区是因为如果数据丢了要重传。只有收到数据已送达的信号才会清空发送缓冲区;

UDP是不可靠传输协议,数据丢了就丢了。没有重传这一概念,因此没有发送缓冲区。

为什么UDP要有接收缓冲区?

因为进行网络通信时,上层要做很多工作。因此OS要提供一个接收数据的能力,上层忙的时候,OS也能缓存一部分报文,如果接收缓冲区满了,再发送报文,则该报文会被丢弃,丢弃后UDP并不会关心。

报文的理解

报文=报头+有效数据载荷;

在OS内部,一定可能会同时存在大量报文。而OS就必须管理这些报文。

所以就有了sk_buff结构体——>内有4个重要指针:head,data,tail,end。

所谓的封装和解包,本质就是移动(+、-对应协议长度)data指针在缓冲区的指向;

UDP使⽤注意事项

我们注意到,UDP协议⾸部中有⼀个16位的最⼤⻓度.也就是说⼀个UDP能传输的数据最⼤⻓度是 64K(包含UDP⾸部).

然⽽64K在当今的互联⽹环境下,是⼀个⾮常⼩的数字.

如果我们需要传输的数据超过64K,就需要在应⽤层⼿动的分包,多次发送,并在接收端⼿动拼装;

基于UDP的应⽤层协议

• NFS:⽹络⽂件系统

• TFTP:简单⽂件传输协议

• DHCP:动态主机配置协议

• BOOTP:启动协议(⽤于⽆盘设备启动)

• DNS:域名解析协议

当然,也包括你⾃⼰写UDP程序时⾃定义的应⽤层协议;

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐