【传输层】网络基础 -- UDP协议 | TCP协议

  • 再谈端口号
    • 端口号范围划分
    • netstat
    • pidof
  • UDP
    • UDP的特点
      • 面向数据报
      • UDP的缓冲区
    • 基于UDP的应用层协议
  • TCP
    • 认识TCP协议的报头
    • 理解封装解包
    • 理解可靠性
    • TCP工作模式
    • 16位窗口大小
    • 6位标志位
      • URG
      • ACK
      • PSH
      • RST
      • SYN
      • FIN

再谈端口号

端口号(Port)标识了一个主机上进行通信的不同的应用程序

【传输层】网络基础 -- UDP协议 | TCP协议_第1张图片

在TCP/IP协议中,用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信(可以通过netstat -n查看)
【传输层】网络基础 -- UDP协议 | TCP协议_第2张图片

端口号范围划分

  • 0 - 1023:知名端口号,HTTP,FTP,SSH等这些广为使用的应用层协议,他们的端口号都是固定的
  • 1024 - 65535:操作系统动态分配的端口号。客户端程序的端口号,就是由操作系统从这个范围分配的

有些服务器是非常常用的, 为了使用方便, 人们约定一些常用的服务器, 都是用以下这些固定的端口号:

  • ssh服务器,使用22端口
  • ftp服务器,使用21端口
  • telnet服务器,使用23端口
  • http服务器,使用80端口
  • https服务器,使用443端口

执行下面的命令, 可以看到知名端口号

cat /etc/services

我们自己写一个程序使用端口号时, 要避开这些知名端口号

一个进程是否可以bind多个端口号? 一个端口号是否可以被多个进程bind?
进程与端口号的关系就是父与子的关系,父亲可以有多个儿子,而每个儿子只有一个父亲。进程可以bind多个端口号,一个端口号只能被一个进程bind。

netstat

netstat是一个用来查看网络状态的重要工具
语法:

netstat +[选项]

功能:查看网络状态
常用选项:

  • n 拒绝显示别名,能显示数字的全部转化成数字
  • l 仅列出有在 Listen (监听) 的服務状态
  • p 显示建立相关链接的程序名
  • t (tcp)仅显示tcp相关选项
  • u (udp)仅显示udp相关选项
  • a (all)显示所有选项,默认不显示LISTEN相关

pidof

在查看服务器的进程id时非常方便
语法:

pidof +[进程名] 

功能:通过进程名, 查看进程id

UDP

【传输层】网络基础 -- UDP协议 | TCP协议_第3张图片

  • 16位UDP长度,表示整个数据报(UDP首部+UDP数据)的最大长度;
  • 如果校验和出错,就会直接丢弃

UDP的特点

UDP传输的过程类似于寄包裹,你只能一个一个寄,而不能寄1.5个。

  • 无连接:知道对端的IP和端口号就直接进行传输,不需要建立连接;
  • 不可靠:没有确认机制,没有重传机制;如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息;
  • 面向数据报:不能够灵活的控制读写数据的次数和数量;

面向数据报

应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并;

用UDP传输100个字节的数据:
如果发送端调用一次sendto,发送100个字节,那么接收端也必须调用对应的一次recvfrom,接收100个字节;而不能循环调用10次recvfrom,每次接收10个字节;

UDP的缓冲区

  • UDP没有真正意义上的 发送缓冲区,调用sendto会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作;
  • UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致;如果缓冲区满了,再到达的UDP数据就会被丢弃;

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

我们用的网络lO接口,其实并不直接是发送和接受接口,而是拷贝接口!
【传输层】网络基础 -- UDP协议 | TCP协议_第4张图片

协议就是结构化数据

UDP使用注意事项:

  • 我们注意到,UDP协议首部中有一个16位的最大长度,也就是说一个UDP能传输的数据最大长度是64K(包含UDP首部)。
  • 然而64K在当今的互联网环境下,是一个非常小的数字。
  • 如果我们需要传输的数据超过64K,就需要在应用层手动的分包,多次发送,并在接收端手动拼装;

基于UDP的应用层协议

  • NFS: 网络文件系统
  • TFTP: 简单文件传输协议
  • DHCP: 动态主机配置协议
  • BOOTP: 启动协议(用于无盘设备启动)
  • DNS: 域名解析协议

当然,也包括你自己写UDP程序时自定义的应用层协议;

TCP

TCP全称为 “传输控制协议(Transmission Control Protocol”). 人如其名, 要对数据的传输进行一个详细的控制;

认识TCP协议的报头

【传输层】网络基础 -- UDP协议 | TCP协议_第5张图片

  • 源/目的端口号:表示数据是从哪个进程来,到哪个进程去;
  • 32位序号/32位确认号:下面工作模式会有说明。
  • 4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最大长度是15 * 4 = 60
  • 6位标志位:(下面会详细说明)
    URG:紧急指针是否有效
    ACK:确认号是否有效
    PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
    RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文段
    SYN:请求建立连接;我们把携带SYN标识的称为同步报文段
    FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段
  • 16位窗口大小:下面会有
  • 16位校验和:发送端填充,CRC校验,接收端校验不通过,则认为数据有问题。此处的检验和不光包含TCP首部,也包含TCP数据部分。
  • 16位紧急指针:标识哪部分数据是紧急数据;
  • 40字节头部选项:暂时忽略;

【传输层】网络基础 -- UDP协议 | TCP协议_第6张图片

  1. tcp协议是有标准长度的:20,先读取20字节

  2. 转换成为一个结构化的数据,立马提取标准报头中的4位首部长度

  3. 就能得到后续报头的剩余大小,x * 4 - 20 = 0; x * 4 - 20 = n;
    tcp报头的总长度,0000-1111,[0,15]
    tcp报文的总长度 = 4位首部长度 * 4字节
    tcp报头的总长度,0000-1111,[0,15],[0,60],[20,60]
    如果我们报头就是20字节,那么4位首部长度,应该填写多少呢?
    x * 4字节 = 20 、x = 5 (0101)

  4. 只要把tcp报头处理读取完毕,剩下的就是有效载荷

理解封装解包

我们收到一个报文,是如何找到曾经bind特定port的进程的?网络协议栈和文件是什么关系?
系统有很多的场景需要我们快速定位一个进程,bind就是将端口号及映射关系插入哈希表中。

【传输层】网络基础 -- UDP协议 | TCP协议_第7张图片

理解可靠性

为什么网络传输的时候,会存在不可靠问题?
【传输层】网络基础 -- UDP协议 | TCP协议_第8张图片
因为距离变长了,导致出现可靠性问题。

不可靠问题常见都有哪些不可靠的场景?
丢包,乱序,校验错误,重复…

如果距离长了,存不存在绝对的可靠性?

比如:小明小红相隔1千米,小明问小红吃饭了吗?这条消息,小明并不能确定小红是否收到。小红回小明:她吃了。这时候小明才能确定她收到了这条消息。

  • 我们认为,只有收到了应答,历史消息我才能100%确认对方收到,确认应答了,才算可靠
  • 双方通信,一定存在最新的数据,没有应答!—最新消息一般无法保证可靠性!

不存在绝对的可靠性,存在相对的可靠性,一个报文只要收到了应答就能保证该报文的可靠性 – 建立在确认应答

TCP工作模式

【传输层】网络基础 -- UDP协议 | TCP协议_第9张图片
双方两个朝向的可靠性,双方在进行通信的时候,可能除正常的数据段,通信时也会涵盖确认数据段
【传输层】网络基础 -- UDP协议 | TCP协议_第10张图片

tcp双方的地位是对等的,只需要搞定一个朝向的通信过程

数据到达对面的顺序一定是和发送的顺序一样的吗?不一定
【传输层】网络基础 -- UDP协议 | TCP协议_第11张图片

注定了应答报文,对应的报头中必定涵盖了确认序号,确认应答和确认序号:接收方已经收到了ACK序号之前的所有(真的所有,且连续)的报文。
【传输层】网络基础 -- UDP协议 | TCP协议_第12张图片

为什么我们要有两组序号
是因为我们tcp通信是全双工的,收发分别对应序号与确认序号:
【传输层】网络基础 -- UDP协议 | TCP协议_第13张图片

16位窗口大小

【传输层】网络基础 -- UDP协议 | TCP协议_第14张图片
因为我们所构建的所有TCP报文都是要给对方发送的,对客户端与服务端一样适用。很明显如果我们知道了对方的缓冲区大小,我们也不需要发送过去了。互相交换接受能力

6位标志位

tcp报文也是有类型的,服务器会收到各种各样的tcp报文,接收方要根据不同的tcp报文,要有不同的动作。tcp正常的数据段,有的就是ack…

URG

URG(紧急)标志位

URG(Urgent)标志位用于指示 TCP 数据包中是否包含紧急数据。它被设置为1时,表示该数据包中的某些数据被标记为紧急数据。紧急数据指示了一种需要尽快处理的情况,通常是一些优先级较高的数据。

当 URG 标志位被设置为1时,还需要使用16位的紧急指针字段(Urgent Pointer)来指示紧急数据在数据流中的位置。紧急指针指示了紧急数据的字节偏移量,从而使接收方能够识别和处理这些紧急数据。

这些紧急数据可以称为带外数据

在 TCP 中,带外数据通过使用紧急指针(Urgent Pointer)和 URG(紧急)标志位来标识和处理。当发送端发送带外数据时,它会设置 URG 标志位,并指定紧急指针的位置,以通知接收端有紧急数据需要处理。接收端在收到带有 URG 标志位的数据时,会根据紧急指针指示的位置来处理这些带外数据。

带外数据的使用可以根据具体的应用协议和实现进行定义。一些常见的应用包括:

  • Telnet 协议:Telnet 协议中使用带外数据来发送终止命令或中断信号,以立即中断当前的操作。
  • FTP 协议:FTP 协议中使用带外数据来传输一些控制信息,例如中断传输或终止文件传输的命令。
  • 窗口大小调整:在 TCP 连接中,带外数据可以用于通知对方调整发送或接收窗口的大小,以便更有效地利用网络带宽。

URG 标志位主要用于紧急数据的通信和处理。当 TCP 连接的一方发送紧急数据时,它可以使用 URG 标志位来通知接收方,以便接收方能够及时处理这些数据。在实际应用中,紧急数据的处理方式和含义可以根据具体的应用协议和实现进行定义。

需要注意的是,URG 标志位的具体使用和处理是由应用层协议和操作系统决定的。因此,不同的应用程序和操作系统可能有不同的处理方式和行为。

ACK

ACK(确认)标志位

ACK(Acknowledgment)标志位用于指示 TCP 数据包中的确认号(Acknowledgment Number)字段是否有效。它被设置为1时,表示 TCP 数据包中的确认号字段包含有效的确认信息。

在 TCP 连接中,数据的传输是通过发送方将数据分割为多个 TCP 数据包并发送,接收方接收到这些数据包后会发送确认信息给发送方。确认信息中包含了接收方期望收到的下一个字节的序号,即确认号。通过设置 ACK 标志位为1,发送方可以知道接收方已经成功接收到了之前发送的数据。
【传输层】网络基础 -- UDP协议 | TCP协议_第15张图片
TCP将每个字节的数据都进行了编号:即为序列号,每一个ACK都带有对应的确认序列号, 意思是告诉发送者,我已经收到了哪些数据;下一次你从哪里开始发
【传输层】网络基础 -- UDP协议 | TCP协议_第16张图片
我们把TCP里的发送缓冲区当做数组,只要将数据从应用层拷贝到了发送缓冲区,每个字节就天然有了序列号。

ACK 标志位在 TCP 的三次握手过程中也起到了重要的作用。在建立 TCP 连接时,客户端和服务器之间会互相发送带有 SYN(同步)和 ACK 标志位的数据包,用于确认连接的建立和同步序号的交换。

需要注意的是,ACK 标志位的具体使用和处理是由 TCP 协议和操作系统决定的。在 TCP 连接中,发送方和接收方会根据 ACK 标志位的设置来确认数据的传输情况,并进行相应的处理。

PSH

PSH(Push)标志位

PSH(Push)标志位用于指示 TCP 数据包中的数据应该被立即推送给应用层,而不是等待缓冲区填满或等待计时器超时。当 PSH 标志位被设置为1时,发送方通知接收方应该立即将接收到的数据提交给上层应用进行处理。

通常情况下,TCP 数据报在发送方的缓冲区中进行累积,直到缓冲区填满或者等待一定的时间才会发送出去。这种方式可以提高网络传输的效率,因为可以将多个数据报一起发送。但在某些情况下,需要立即将数据推送给接收方的应用层。

例如,在实时通信或交互式应用中,延迟会对用户体验产生不利影响。通过设置 PSH 标志位为1,发送方可以指示接收方在接收到该数据报后立即将数据提交给应用层处理,从而减少传输延迟。

需要注意的是,PSH 标志位的具体使用和处理是由应用层协议和操作系统决定的。应用程序和操作系统可以根据自身需求来决定何时设置 PSH 标志位,以满足特定的数据传输要求。

RST

RST(复位)标志位

RST(Reset)标志位用于指示 TCP 数据包中的复位请求。当 RST 标志位被设置为1时,它表示发送方或接收方希望立即中断当前的 TCP 连接,并进行连接的复位操作。

RST 标志位通常用于表示发生了严重的错误或异常情况,导致当前的连接无法继续进行。当一方发送带有 RST 标志位的 TCP 数据包时,它相当于向对方发送了一个连接复位请求,要求对方放弃当前的连接并重新建立新的连接。

RST 标志位的使用场景包括:

  • 非法连接或攻击:当网络设备或应用程序检测到非法连接或攻击时,可以发送带有 RST 标志位的数据包,以中断与攻击者的连接并保护系统的安全。
  • 异常情况处理:当发生一些严重的异常情况,如网络故障、连接超时或协议错误等,可以使用 RST 标志位来中断当前的连接并重新建立新的连接。
  • 拒绝服务防护:在面对拒绝服务(DoS)攻击或过载情况下,网络设备或服务可以使用 RST 标志位来拒绝新的连接请求,并释放已建立的连接资源。

需要注意的是,RST 标志位的具体使用和处理是由 TCP 协议和操作系统决定的。在收到带有 RST 标志位的数据包时,接收方会根据协议规定的处理方式来中断连接并进行相应的处理。

SYN

SYN(同步)标志位

SYN(Synchronize)标志位用于在建立 TCP 连接时进行同步和协商。在 TCP 的三次握手过程中,SYN 标志位扮演了重要的角色。

当发送方希望建立一个新的 TCP 连接时,它会发送一个带有 SYN 标志位的数据包给接收方。这个数据包中包含一个初始序列号(Initial Sequence Number),用于标识数据流的起始位置。通过设置 SYN 标志位为1,发送方告诉接收方它希望建立一个新的连接,并将初始序列号设置为指定的值。

接收方收到带有 SYN 标志位的数据包后,会发送一个带有 SYN 和 ACK(确认)标志位的数据包作为回应。这个数据包中包含确认号(Acknowledgment Number)字段,表明接收方期望收到的下一个字节的序号,并且也包含一个自己选择的初始序列号。

最后,发送方收到接收方的 SYN+ACK 数据包后,会发送一个带有 ACK 标志位的数据包作为确认。这个数据包中的确认号字段表示发送方期望接收到的下一个字节的序号。

通过这个三次握手的过程,发送方和接收方可以建立起双向的、可靠的 TCP 连接,并同步序列号和确认号,以确保数据的可靠传输。

需要注意的是,SYN 标志位的具体使用和处理是由 TCP 协议和操作系统决定的。在 TCP 连接的建立过程中,发送方和接收方会根据 SYN 标志位的设置和响应来完成连接的建立和同步操作。

FIN

FIN(结束)标志位

FIN(Finish)标志位用于表示发送方已经完成发送数据,并且要求关闭连接。当一个 TCP 连接的一方发送带有 FIN 标志位的数据包时,它表示它已经没有更多的数据要发送,并且希望关闭连接。

FIN 标志位的使用场景包括:

  • 正常关闭连接:当发送方发送完所有的数据后,它会发送一个带有 FIN 标志位的数据包,告知接收方已经没有更多数据需要发送,并请求关闭连接。
  • 异常关闭连接:在某些情况下,连接的一方可能会遇到异常情况,如应用程序崩溃、网络故障或连接超时等。在这种情况下,该方会发送带有 FIN 标志位的数据包,以请求关闭连接,并指示对方不要再发送数据。

当一方收到带有 FIN 标志位的数据包时,它会发送一个带有 ACK(确认)标志位的数据包作为确认,表示已经收到关闭请求。然后,它也可以选择发送带有 FIN 标志位的数据包,表示它也已经完成发送数据,并请求关闭连接。

通过这种方式,双方可以逐步关闭连接,确保双向的数据都已经发送完毕,并最终关闭连接。

需要注意的是,FIN 标志位的具体使用和处理是由 TCP 协议和操作系统决定的。在 TCP 连接关闭过程中,发送方和接收方会根据 FIN 标志位的设置和响应来完成连接的逐步关闭。


如有错误或者不清楚的地方欢迎私信或者评论指出

你可能感兴趣的:(Linux网络基础,网络,udp,tcp/ip)