[Linux] 网络基础(探索应用层与传输层TCP与UDP原理)


基础引入

应用层

应用层负责应用程序之间的数据沟通

  1. 自定制协议
  • 序列化:将数据按照持久化存储网络数据传输的格式进行排布。
  • 反序列化:对数据以指定的协议进行解析。

url:统一资源定位符。(俗称网址)其中包含:

协议名称 :// 用户名 : 密码 @ 服务器地址 : 服务器端口 / 资源路径 ? 查询字符串 # 片段标识符

URL编码和解码 :
因为url中特殊字符都具有特殊含义,因此查询字符串(用户提交的数据)中若有特殊字符存在,则会造成数据二义性,因此需要对用户提交的数据进行urlencode操作。

  • urlencode:将特殊字符转换为十六进制字符串,在编码字符前方使用%表明字符已经编过码,需要解码。
  • urldecode:当查询字符串中出现%,则认为后续字符是需要url解码的。

例如C++这几个字符将会编码为C%2b%2b

  1. 知名协议

HTTP协议

http是应用层协议,在传输层使用tcp协议实现,默认端口为80
http是一个短连接,但在http 1.1中实现了长连接。)

协议格式:请求首行、请求头部、空行、正文。

请求首行

  1. 请求首行:请求方法(GETPOST等)、URL、协议版本(HTTP( 0.9 / 1.0 / 1.1 / 2))。(数据间以空格间隔)

get所提交的数据在url中,明文形式,肉眼可以看到,所以不安全。
post提交的数据在正文中,安全

  1. 响应首行:协议版本、响应状态码、状态码描述。
    状态码:1xx2xx3xx4xx5xx
    常见的状态码:
    200:OK
    302:临时重定向
    404:page not found
    502:bad gateway(坏的网关)

请求头部

头部由一个个键值对的头部信息组成。

键值二者之间以:(冒号 + 空格)间隔。

每个键值对都有其含义和功能。格式 key:value\r\nkey:value\r\n
(连续遇到2\r\n就认为是头部信息结束了)

另外包含Content-Length/Content-Type/refer/Set-Cookie/Transfer-Encodeing/Location信息等。

空行

本质上是:\r\n

正文

什么格式数据都有 ~

使用封装的tcpsocket完成实现一个简单的http服务器

本质上就是在tcp服务器的基础上进行http协议数据的解析。

解析过程

  1. 获取http头部(首行 + 头部)
    首行中包含url可以知道客户端申请什么资源,GET请求还可以获取到提交的数据。
    首行中包含的协议版本:拿到版本就可以针对不同版本的特性进行处理。
  2. 解析头部
    可以获取到正文有多长,正文是什么类型的数据。
  3. 获取正文,进行处理
    (通常将正文交给子进程处理)
  • Q:如何获取头部/如何保证获取一个完整的头部?
  • A:可以MSG_PEEK探测性接受

传输层

传输层负责端与端之间的数据传输TCP/UDP

  • 端口号:在一台主机表示一个进程。
    类型:uint16_t
    范围:0~65535 (其中0~1023不推荐使用,存在预留)

操作系统获取到网卡接收的数据,通过端口就知道数据该放到哪一个socket的缓冲区中。

一个端口号只能被一个进程占用,一个进程可以占用多个端口号。

五元组:
一条网络上的数据包含的五条信息:源ip + 源端口 + 目的ip + 目的端口 + 协议

主机上网络状态的查看:netstat -anptu

传输层的传输协议
UDP:无连接、不可靠、面向数据报。要求向应用层整条数据接收、交付,不会出现半个数据,因为头部中有报文长度标识,否则就需要额外维护 / 管理了。
也正是因为数据报长度在协议头中有标识,所以udp不会产生黏包问题。

面向数据报:数据整条收发,灵活性低,但不会造成黏包问题。
udp协议包含字段:源端口、目的端口、数据报长度、校验和。

  • 源端口/目的端口:传输,确定数据应该哪个进程处理。
  • 校验和:二进制的反码求和。
  • 数据报长度:uint16_t类型。
    意味着udp数据报最大长度为64k - 8(因为包含8位的udp头部),若sendto给的数据大于64k则会报错。因为udp在传输层不会进行数据分段。
    若传输的数据大于64k,用户需要在应用层将数据分割成一个个小段,进行传输。
    udp传输并不保证数据报的有序到达。(有可能会乱序),因此也需要用户在应用层进行包序管理

udp协议实现了传输层广播数据包。

TCP协议

tcp协议可以保证包序。

tcp连接管理

面向连接,可靠传输、面向字节流

在这里插入图片描述

TIME_WAIT的作用:

  1. 假设没有TIME_WAIT会有什么情况?
    答:最后一个ACK丢失

被动关闭方重发FIN包,没有等待直接关闭。若直接启动的客户端又使用相同端口信息,有可能收到FIN包,对新连接造成影响。
若新启动客户端使用相同端口信息,向服务端发送SYN请求,但是被动关闭方(服务端)因为没有收到最后一个ACK,处于LAST_ACK状态,收到SYN后判定状态错误。同时会符RST报文,重置连接,也对新连接造成影响。

  1. 因此主动关闭方收到发送最后一个ACK之后需要等待一段时间(2MSL时间):
    一、 处理若ACK丢失,导致对端重传的FIN包。
    二、等待网络中所有双方延迟的报文消失在网络中,不会对后续造成影响。

为什么握手是三次,而挥手是四次?
若三次握手的时候第三次握手失败,服务器如何处理?
SYN泛洪攻击?
TIME_WAIT状态的作用?
为什么服务端出现了大量的TIME_WAIT连接? 如何解决?

  • Q:如果服务端程序TIME_WAIT无法理解重启,也可以说是此端口暂时无法使用、无法立即重启
  • A:修改参数(setsockopt

可靠传输

确认应答机制、超时重传机制(保证数据安全到达)、协议字段中的序号 / 确认序号(保证数据有序到达)

因为tcp为了实现可靠传输牺牲了部分传输性能,而且有可能因为ACK确认应答丢失也要重传数据,因此又提出了以下几种机制来避免大量的丢包重传以及ACK丢失重传,来提高性能:

  1. 滑动窗口机制:通过协议字段中的窗口大小,双方进行协商,一次可以最多传输多少数据,之后等待确认应答,不需要进行一对一的停等。
    快速重传机制 + 流量控制 + 拥塞控制

流量控制TCP通过双方协商窗口大小进行流量控制,避免因为缓冲区数据塞满而大量丢包重传。

快速重传机制

  1. 每条数据的确认回复都必须按序回复,如果前面的数据没有收到,则不会对后面的数据进行回复(乱序的情况),意味着若接收到一条回复,表示ACK确认序号之前的数据全部安全到达,不会因为前面数据的ACK丢失而重传数据。
  2. 若前面的数据丢失,则接收方收到后面发送的数据,立即发送重传请求,并且连发三次。若发送方连续收到三条重传请求,则认为数据丢失,进行重传。

拥塞控制慢启动,快增长
发送端控制一个拥塞窗口大小,在进行数据传输的时候,进行网络探测式的发送。

  • 若网络状况良好,则发送的数据快速增长(指数级),达到阈值(窗口大小)时,则不再继续增长。
  • 若传输过程中出现丢包,则重新初始化拥塞窗口。重新慢启动,快增长。

拥塞控制为了避免因为网络状况不好导致通信初始,大量的数据包丢失重传,降低性能。

  1. 延迟应答机制
    接收方收到数据后并不立即进行确认回复,而是等待一段时间,因为这段延迟的时间内,有可能用户已经recv,将缓冲区中的数据读取走,窗口就可以尽可能的保证最大大小,保证传输吞吐量。

  2. 捎带应答机制
    接收方对每一条的确认回复都需要发送一个TCP数据报,但是空报头的传输会降低性能,因此会在即将要发送的数据报头中包含有确认信息,可以少发送一个用于确认的空报头。


面向字节流

意为:传输字节流。

特性:传输灵活

发送方每次调用sendto都会将数据放到缓冲区中,然后内核选择合适时机发送数据。
接收方网卡接收到数据,都会将数据放到接收缓冲区中,用户recv就是从接受缓冲区中取数据。

缺点:黏包问题

  • 主要发生的位置在于:发送缓冲区 / 接收缓冲区 中的数据堆积
  • 本质原因:
    传输层的TCP协议栈对数据之间没有明显边界TCP只管传输数据的字节流,导致发送端/接收端因为数据的堆积在实际发送或者recv一次获取到半条或多条数据。
  • 如何解决TCP黏包?
    虽然TCP在传输层没有数据边界,但是用户可以在应用层进行边界处理

【边界处理常见方法】:

  1. 特殊字符处理(如HTTP协议)
  2. 定长数据(如UDP头中包含长度)
  3. 变长数据,在数据包头汇总声明数据长度。

TCP有黏包问题,但UDP没有黏包问题。
TCP相较于UDP传输性能较低。
TCP安全传输,UDP不安全传输。

  • TCP断开连接:
    TCP协议栈有自身的保活机制:长时间无数据通信,则发送保活探测包。若多次没有收到回应,则认为连接断开。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

giturtle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值