Linux----网络传输层UDP/TCP

Posted 4nc414g0n

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux----网络传输层UDP/TCP相关的知识,希望对你有一定的参考价值。

网络传输层UDP/TCP

引入

①端口号

端口号标识一个主机上进行通信的不同程序
在TCP/IP协议中, 用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信

②端口号划分

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

③知名端口号

比如:

  1. ssh服务器, 使用22端口
  2. ftp服务器, 使用21端口
  3. telnet服务器, 使用23端口
  4. http服务器, 使用80端口
  5. https服务器, 使用443
  6. sunproxyadmin: 使用8081端口

执行命令vim /etc/services可以查看端口号

④netstat、pidof、killall、ps、 awk、xargs????

netstat:
语法: netstat [选项]
功能:查看网络状态
常用选项:

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

例如tcp:

pidof 【进程名】:查看进程的pid

killall
功能:kill和ps grep等的结合体,用来使用进程名称来杀死进程
参数:

  1. -e:对长名称进行精确匹配;
  2. -l:忽略大小写的不同
  3. -p:杀死进程所属的进程组;
  4. -i:交互式杀死进程,杀死进程前需要进行确认;
  5. -l:打印所有已知信号列表
  6. -q:如果没有进程被杀死。则不输出任何信息;
  7. -r:使用正规表达式匹配要杀死的进程名称;
  8. -s:用指定的进程号代替默认信号“SIGTERM”;
  9. -u:杀死指定用户的进程

ps axj | grep 【进程名】:查看为【进程名】的所有进程
ps axj | hread -nl && ps axj | grep 【进程名】
ps axj | grep 【进程名】| grep -v grep | awk ‘print $2’ | xargs kill -p//第二列
gawk 列处理工具
输入记录中的每个字段都可以通过其位置来引用:$1、$2 等等。 $0 是整个记录。字段不需要被常量引用: n = 5 print $n 打印输入记录中的第五个字段
xargs :Linux xargs 命令

⑤所有协议需要解决的两个问题:

需要解决:

  1. 如何将自己的报头和有效载荷分离的问题
  2. 任何协议都必须解决,要将自己的有效载荷交付给,上层的哪一个协议

1)UDP

①UDP协议段格式


16位UDP长度, 表示整个数据报(UDP首部+UDP数据)的最大长度;如果校验和出错, 就会直接丢弃
所有协议需要解决的两个问题(对于UDP):

  1. 通过定长报头
  2. 16位目的端口号
    1.为什么socket编程中的port是16位的因为协议是16位的 2.为什么server要绑定,因为需要向上层协议交付

UDP或者TCP是在内核里面,tcp/ ip协议栈,本质也是Linux内核的一部分
由于Linux内核是用C语言实现的-->内核中,我们的报头其实是位段

struct udp_header 
	uint32_t src_ port: 16
	uint32_t dst_ port:16;
	uint32_t udp_ length: 16:
	uint32_t udp_ check: 16;

位段是一种类型,可以定义变量->开辟空间,保存数据->填充报头本质上就是给位段类型对应的变量赋值

②UDP缓冲区

sendto, recvfrom,read,write,send, recv等本质并不是把数据发送到网络中,而是将用户数据拷贝到udp/tcp的发送缓冲区,或者将内核缓冲区中的数据,拷贝到用户
OS中的传输层协议来决定什么时候发送数据,发送多少数据,丢包了该干嘛(UDP丢包了不管)


UDP具有接收缓冲区. 但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致; 如果缓冲区满了, 再到达的UDP数据就会被丢弃;
UDP的socket能同时读写,全双工

③UDP特点及注意事项

UDP传输的过程.

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

注意事项:

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

④基于UDP的协议

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

2)TCP

引入

冯诺伊曼体系结构中,(硬件与硬件之间是互相独立的)独立组件是通过“线”做到数据的传导的 即便是在本主机内部,各个设备间都要有自己的协议(功能性问题,比如SCSI HBA PCI …)


专门设计TCP/IP协议是因为通信的设备之间“线更长了,传播的距离更远了,数据更容易丢失

  1. TCP解决传输过程中的可靠性问题
  2. IP解决定位设备问题

所以万物皆可系统化,皆可网络化

①TCP协议段格式

首先:任何协议都要先解决的两个问题:

  1. 分离有效载荷 (位首部长度,定长报头+自描述报头长度4bit(包括选项) 区分报头和有效载荷)
  2. 将有效载荷传给上一层协议 ( )

TCP协议段格式:

注意:

  1. 这里的4位首部长度,单位是四字节,比如:如果报头长度20个字节,4位首部长度就是20/4=5 二进制0101
  2. 标准的TCP报头为20个字节最大报头长度为60字节(可携带选项40字节)(4位首部长度-20就可判断是否继续读取option)

32位序号 和 32位确认序号

确认应答机制(ACK)保证了可靠性

  • 不是对最新数据的可靠性保证 (最新数据可靠性不能被保证,只有收到应答才代表发出的消息被收到,可靠) ,而是对历史数据的可靠性进行保证

TCP是全双工的

  • 需要保证双向可靠性,双方需要确认应答机制,并遵守

host1向host2发送消息不一定是发一条,host2回一条,可能是发送多条,host2再回复多条,在这个过程中,每个报文可能选择的路由路径都是不同的,不同路径的通畅程度也不同(不可靠)

  • 所以,在TCP的报头中有序号,可以对报文进行顺序重排(保证按序到达)

无论是请求还是应答都是:

  • tcp数据段:tcp报文+有效载荷 (应答可能没有有效载荷)

为什么要有一对32位序号?

  • 任何请求可能是应答也可能是数据发送,所以,需要确认序号,来对对方的报文进行确认,同时也需要序号来保证报文到对方的按序到达


注意图中没有体现出带字节数据的情况


32位序号:(参考关于ISN

  • 初始序列号(ISN),是客户端随机产生的一个值,初始序列号(ISN)随时间而变化的,而且不同的操作系统也会有不同的实现方式 之后序号就是对方的确认序号

32位确认序号(32位序号+1):

  • 告诉发送者下一次从哪里开始发
    注意:确认号是第一次发送的时候是0之后是对方发来的序号+1
    (比如发送方发送了一个报文段序号为301的TCP段,这个段携带了100字节数据,则接收方应当回复的确认号是401)

16位窗口大小

TCP有自己的发送缓冲区和接受缓冲区,结合到之前的socket编程

  1. write,send…本质是将用户数据拷贝到TCP的发送缓冲区
  2. read,recv…本质是将内核的TCP缓冲区数据,拷贝到用户的缓冲区

当发送的数据过大,对方来不及接收, 16位窗口,表明自己的接收能力(接收缓冲区中剩余的空间大小)
站在OS的角度:

这种通过互相通报自己的接收能力(16位窗口大小)给对方,以达到两个方向上的传输速度的控制叫做流量控制
同时也可以看作在网络层面上生产者消费者的应用

16位紧急指针

因为tcp是按序到达的, 所以,如果想让后续的数据被优先读取并处理,是不可能的,所以TCP提供了优先处理数据的能力,就是设置TCP中的URG标志位,紧急数据标志位,结合紧急指针使用(只能有一字节的紧急数据)

在socket编程中send和recv有一个flag选项:可以填写MSG_OOB来设置紧急数据和优先处理紧急数据

  • send
  • recv

6位标志位(16位紧急指针)

标志位(0 or 1)作用
URG(urgent)紧急指针是否有效
ACK(acknowledgement)确认号是否有效
PSH(push)提示接收端应用程序立刻从TCP缓冲区把数据读走
RST(reset)对方要求重新建立连接; 我们把携带RST标识的称为复位报文段
SYN(synchronous)请求建立连接; 我们把携带SYN标识的称为同步报文段
FIN(finish)通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段

为什么一定要SYN:

  • 服务器收到tcp报文的时候,一定会在同一时间段,收到多种报文,为了保证数据正常通信,此时接收方就使用SYN如何区分, 这些报文中,哪些是断开链接,哪些是建立链接的

解释RST:

  • 在三次握手场景中如果最后一次ACK失败,client会仍然认为建立是成功的(第三次没有应答),server会认为建立链接失败,在这时,认为成功的client就会向server发送数据,server在建立连接失败的情况下收到数据就会向client发送RST=1,要求重新建立连接

为什么一定是三次握手:

  • 假设我们是4次握手,也就是多了一次ACK,但是更重要的是,认为建立连接成功的一方由client变为了server
    连接可能很多,OS需要管理,(维护一个链接是有成本的(时间+空间), 且建立连接并不是必须100%建立成功,如果黑客想要攻击server,只需要向server发起大量的连接请求,但是在最后一次时不接收server的ACK,这样server认为建立成功,增加大量维护连接的成本,导致瘫痪,所以我们必须使用奇数次的握手
  • TCP是全双工的,需要SYN - > SYN+ACK 一来一回两次验证网络信道的通畅程度,所以三次是成本最低的选择

②确认应答(ACK)机制(Linux内核 MARK)

TCP将每个字节的数据都进行了编号. 即为32位序列号(sequence number)
TCP发送与接收缓冲区,可以简单理解为字符数组char send_buffer[MAXSIZE], char recv_buffer[MAXSIZE], 数组下标就是天然的序列号(操作系统中是用其他方式实现的)

③超时重传机制

有两种情况会触发超时重传机制:

1.ACK丢包

  • 当在间隔时间内client向server发送数据,仍会触发RST
  • 重传SYN+ACK重复的解决方案(TCP层有去重能力,每个报文都有序列号)

2.普通丢包


间隔时间:

  1. 但是这个时间的长短, 随着网络环境的不同, 是有差异的.
  2. 如果超时时间设的太长, 会影响整体的重传效率;
  3. 如果超时时间设的太短, 有可能会频繁发送重复的包

TCP为了保证无论在任何环境下都能比较高性能的通信, 因此会动态计算这个最大超时时间.

  1. Linux中(BSD Unix和Windows也是如此), 超时以500ms为一个单位进行控制, 每次判定超时重发的超时时间都是500ms的整数倍.
  2. 如果重发一次之后, 仍然得不到应答, 等待 2*500ms 后再进行重传.
  3. 如果仍然得不到应答, 等待 4*500ms 进行重传. 依次类推, 以指数形式递增.
  4. 累计到一定的重传次数, TCP认为网络或者对端主机出现异常, 强制关闭连接

以上是关于Linux----网络传输层UDP/TCP的主要内容,如果未能解决你的问题,请参考以下文章

TCP/IP 6 TCP与UDP

TCP与UDP的区别

传输层UDP/TCP协议

TCP和UDP基本原理

TCP/IP 协议图--传输层中的 TCP 和 UDP

第七章 TCP和UDP原理