传输层是计算机网络中的一层,位于网络层和应用层之间。它主要负责在网络中的两个端系统之间提供可靠的、端到端的数据传输服务。简单理解,传输层就是负责在源主机和目标主机之间提供端到端的数据传输。
传输层的两个主要协议有传输控制协议(TCP)和用户数据报协议(UDP)两种。
上述示例只是传输层协议在网络中的部分应用示例。传输层还有其他更广泛的用途,如文件传输、电子邮件传输等。无论使用TCP还是UDP,传输层的目标是确保数据在源和目标之间有效且可靠的传输,同时提供所需的服务质量。
端口号(Port)标识了一个主机上进行通信的不同的应用程序。在TCP/IP协议中,用“源IP”,“源端口号”,“目的IP”,“目的端口号”,“协议号”这样一个五元组来标识一个通信(可以通过netstat-n查看)。
我们来仔细思考一下其中的细节:IP地址标识了全网里唯一一台主机。Port端口号标识了一台机器上的一个应用程序,也可以理解为Port端口号标识了一台机器上的唯一一个进程(一个端口号只能绑定一个进程)。IP地址和Port端口号不就是标识了全网里唯一进程吗!!!网络通信本质上不就是进程间通信吗?那么现在再回过头看“源IP”,“源端口号”,“目的IP”,“目的端口号”,“协议号”这样一个五元组来标识一个通信也就不难理解了。
端口号范围划分是为了网络通信中识别和区分不同的应用程序或服务而定义的。根据传输层协议的不同,端口号的范围也是有所区别的。
在TCP和UDP协议中,端口号范围被划分为以下几类:
注册端口(Registered Ports):从1024到49151的端口号被分配给用户注册的应用程序和服务。这些端口号可以被普通用户打开,但应该避免与已知的知名端口冲突。
动态/私有端口(Dynamic/Private Ports):从49152到65535的端口号是动态或私有端口,用于临时的、非注册的应用程序和服务。这些端口号可以被任何用户的应用程序使用,通常用于客户端与服务器之间的临时通信。
需要注意的是,端口号的范围划分并不是严格规定的,而是一种通用的约定。在实际应用中,为了避免冲突和提高安全性,建议遵循这种范围划分并选择未使用的端口号进行应用程序的开发和部署。
当提到知名端口号时,我们指的是一些常用的端口号,这些端口号在整个互联网上是公认的,并且被用来提供特定的网络服务。以下是一些常见的知名端口号及其对应的服务:
这些端口号只是一部分知名端口号,实际上还有许多其他的端口号用于提供各种特定的网络服务。
我们可以通过cat/etc/services查看知名端口号。
netstat(Network Statistics)是一个用于显示网络连接、路由表和网络接口等相关信息的命令。它可以提供以下方面的详细信息:
具体选项如下:
netstat -a // 显示所有活动的网络连接和监听端口
netstat -n // 以数字格式显示所有连接
netstat -p // 显示与连接关联的进程ID
netstat -t // 显示TCP连接
netstat -u // 显示UDP连接
netstat -l // 显示Listen(监听)的服务
pidof命令用于根据进程名来查找运行中的进程的PID(进程标识符)。 常用用法:pidof+进程名,来查询进程的PID。
我们直接先来学习一下UDP的报文,如下图:
根据上图,我们能很好的总结出UDP报文的结构如下:
UDP报文头部(固定8字节):
- 源端口(源端口号,2字节):表示发送端的端口号。
- 目的端口(目的端口号,2字节):表示接收端的端口号。
- UDP长度(2字节):表示UDP报文的长度,包括头部和数据部分。
UDP校验和(2字节):用于验证UDP报文的完整性,检测是否出现传输错误。
数据部分: UDP报文的数据部分可以包含任意大小的数据(可以没有),没有固定的格式要求。它是应用层传递给UDP协议的数据,在传输过程中,UDP会将整个数据部分封装为UDP报文并发送。
任何协议都要解决的两个问题:1、如何分离和封装;2、如何向上交付。
怎么分离和封装呢?首先UDP报头是有固定长度的,这就很好的解决了。怎么理解UDP报文的报头呢?其实UDP报头在底层就是用一个结构体来封装的,再加上位段就可以很好的实现对UDP报头的封装。代码如下
struct udp_hdr
{
uint32_t source:16; // 源端口号
uint32_t dest:16; // 目标端口号
uint32_t len:16; // UDP报文长度(包括报头和数据部分)
uint32_t check:16; // 校验和
};
UDP的报头加上传输数据不就是UDP报文吗!分离时报头中有报文长度字段,直接减去报头的8个字节,剩下的就是所传输的数据。
向上交付也不难,有目的端口和目的IP地址,就可以很好的找到目标进程进而传输数据。
UDP(User Datagram Protocol,用户数据报协议)是一种在网络通信中常用的传输层协议。与TCP(Transmission Control Protocol,传输控制协议)不同,UDP是一种无连接协议,它提供了一种简单的、不可靠的数据传输服务。
UDP的特点:
无连接性:UDP是一种无连接协议,发送方不需要在发送数据之前与接收方建立连接。每个UDP数据报都是独立的,有自己的头部信息,可以独立地进行传输。这种无连接性使得UDP具有较低的传输延迟和较小的开销。
不可靠性:UDP不提供数据包的可靠交付。一旦发送数据,UDP就不会对数据包进行确认或重新发送丢失的数据包。这意味着UDP在数据传输过程中可能会发生数据包丢失、重复、乱序等情况。因此,如果应用对数据传输的可靠性要求较高,则不适合使用UDP。
高效性:由于UDP无需建立连接和维护状态信息,因此它的开销较小,数据报的头部相对较小。同时,UDP也不会进行拥塞控制,因此在网络负载较大时,UDP可以更高效地传输数据。
面向数据报文:UDP把应用层交给传输层的报文信息进行封装,形成UDP数据报进行传输。这意味着UDP在传输过程中不会对数据进行拆分和合并,保持了数据的完整性。
面向数据报的简单理解:应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并。用UDP传输100个字节的数据,如果发送端调用一次sendto, 发送100个字节,那么接收端也必须调用对应的一次recvfrom,接收100个字节。 而不能循环调用10次recvfrom, 每次接收10个字节。
需要注意的是,由于UDP的不可靠性和无连接性,它在某些情况下可能会导致数据丢失或乱序。
这里需要注意的是,UDP的不可靠并非是一个缺点,也并非是贬义词。只是在相比之下,与UDP相对的是TCP(Transmission Control Protocol),它是一种可靠的协议,提供了数据传输的可靠性和顺序性。但UDP协议的简洁和低延迟特性使其在某些特定的应用场景中具有一定的优势。
UDP没有真正意义上的发送缓冲区。调用sendto会直接交给内核, 由内核将数据传给网络层协议进行后续的传输动作
UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致;如果缓冲区满了, 再到达的UDP数据就会被丢弃。
UDP的socket既能读也能写,这个概念叫做全双工。所谓全双工通信是指同时实现双方之间的双向数据传输,即在同一时间既能发送数据也能接收数据。
UDP协议本质上是一种简单的数据报传输协议,它不维护连接状态,也不提供可靠性保证和流控制。每个UDP数据报都是独立的,它们相对独立地发送和接收,不会受到之前或之后数据报的影响。