当前位置: 首页 > news >正文

网络协议的原理及应用层

网络协议

网络协议目的为了减少通信成本,所有的网络问题都是传输距离变长的问题。

协议的概念:用计算机语言来发出不同的信号,信号代表不同的含义,这就是通信双方的共识,便就是协议。

协议分层(语言层和通信设备层):

软件层优势:为了解耦,分层后,对任意一层做更改,不会影响其它层,一层出问题,不影响系统正常工作,为了更好的封装。

分层方式的优势:功能比较集中,耦合度比较高的模块放在同一层,高内聚。

分层依据:

每一层都要解决特定的问题

第一个问题:传递数据的能力

第二个问题:朝那个方向去传数据,就是路径选择能力

第三个问题:网络容错的纠错能力

第四个问题:解决数据应用方面的能力

 OSI七层模型

上三层:应用能力,由用户去实现,去设置。

TCP/IP五层协议

物理层,数据链路层,网络层,传输层,应用层(负责建立和断开通信连接,网络传输格式,针对特定应用的协议)。

物理层(硬件):光/电信号的传递方式,主要是硬件电路。集线器(Hub)作用:当信息长距离传输时,信号衰弱时,可以进行信息放大,增大传播距离。调制解调器(modem)作用:负责信号的转换,把模拟信号和数字信号互相转换,用光纤连接到路由器,路由器构建成局域网。双绞线:水晶头作用:当作网线来使用。解决传输速率和距离,抗干扰能力。

数据链路层:网卡:连着网线,0/1信号的传输和识别 驱动程序实现

网络层:路径选择,地址和路由管理 os实现

传输层:纠错,确保两台主机之间通信数据可靠性 os实现

系统调用在两者之间

应用层:应用程序的实现

网络传输基本流程

局域网下:.协议报头:每层都有协议,而每一个协议最终表现就是协议都要有报头。而这个报头的作用就是包装数据的信息的容器,类似于快递单,而信息就是协议,类似于快递单的内容。协议通常时通过协议报头来表达的。每一份数据最终在被发送或者在不同的协议层中,都要有自己的报头。

IP地址(局域网和广域网)

规则:IPv4协议(点分十进制)

概念:IP地址是用来标识网络中不同主机的地址,用32位来表示。用来表示从起始位置到终点,IP地址提供方向,位置不会发生变化,它决定了途径点,方便进行路径选择。类似于:从哪里来,到哪里去。

MAC地址(局域网)

概念:地址会变化,位置变化,mac就会变化,阶段目的地。类似于:上一站来自哪里,下一站去哪里。

应用层

网络套接字

套接字有:网络套接字,域间套接字等

端口号(port)

概念:1.2个字节 2.端口号告诉os,网络通信的数据要给那个进程 3.IP地址和端口号能够标识网络上的某台主机的某一个进程。4.一个端口号只能被一个进程占用

需知两台主机通信目的:

把数据从A从到B的过程只是传输手段,不是目的。目的是:两台机器上面的软件通信。

数据有公网IP来标识一台唯一的主机。而端口号标识主机上的服务器进程,客户端进程的唯一性,让os将数据给哪一个进程。

网络通信的本质是进程间间通信通过IP地址+端口号进行唯一标识,然后客户端进程和服务器进程的通信。而网络通信的操作就是IO(发出数据,让别人看到数据)

规则:

IP全网唯一,端口号主机内部唯一。一个端口号一个进程,多个端口号一个进程。

端口使用的原因:

系统是系统,网络是网络,这一原理决定了,需要一个不同于pid的数字来标识网络中的进程,强耦合。其次,存在单机的进程,它有pid而没有端口号,因此这种进程需要用有无端口号来辨别它是否单机。pid会轻易发生改变,而端口号不能随意发生改变,因为需要客户端每次都能找到服务器进程。

端口号的用法:

IP地址+端口号进行唯一标识一个主机中唯一个进程,os通过哈希表的方法用端口号映射文件描述表,找到文件,拷贝到缓冲区,这个就是网络通信需要的进程。而进程的pid也是为了通过哈希表映射,完成一定目的。发送数据需要知道自己的端口(源端口)和传递位置的端口(目的端口),这样才能通过端口号找到进程。

TCP协议(SOCK_STREAM)

面向连接,服务端做好后,还需要与客户端建立三次握手后,才能进行交流,这三次交流就是客户端申请链接,服务端同意链接回复客户端,客户端再进行发消息。服务端需要用listen进行监听状态,然后获取新连接accept(不能使用udp的recvfrom,sendto,因为必须被连接)

1.认识TCP协议的报头

2.如何封装解包,分用

解包tcp协议有标准长度20,先取20字节,这个20字节一定可以转换为结构化数据,立马提取标准报头中4位首部长度(tcp报头的总长度0000-1111,取值范围[0~15]),tcp报文的总长度=4位首部长度*4字节  报头总长度[0,60],[20,60]字节

分用:报头有目的端口号,就可以找到应用层的进程,数据就可以交付给进程。系统有很多进程,os会以端口号来维护哈希表找到进程PCB。

3.理解TCP的报头

一个结构体包含 源端口号,目的端口号,序号,确认序号,首部长度

结构体的对象添加数据,然后转到缓冲区就是添加报头

4.可靠性

不可靠的原因就是距离边长了,不可靠的场景丢包,乱序,校验错误,重复

1、只有收到应答,才知道对方收到了,历史消息保证可靠性

2、双方通信,一定存在新数据,没有应答,最新消息无法保证可靠性

3、不存在绝对可靠性,相对可靠性是基于确认应答

UDP协议(SOCK_DGRAM)

无连接,服务端做好,客户端就可以直接对服务端发消息

问题1:传输过程

相同点:

服务器的启动方式是相同的,都是用本地ip+端口号

区别:

网络字节序列

内存中的多字节数据相对于内存地址有大小端之分。

网络传输中的数据以先发的数据是低地址的,后发为高地址的,都是以大端传输的,而发送主句通常将数据按内存地址从低到高的顺序发出。接收主机从网络上接到的字节依次保持在接收缓冲区中,也是按内存地址从低到高的顺序保存。

大端:高权值位放低地址

小端:高权值位位放高地址

而网络是按照大端的方式存储的,而主机取决于程序员。

这是网络字节序按相应的方式与主机字节序转换的接口。

其中h代表主机,to是前一个转后一个,n是网络,l表示32为长整型,s表示16位短整型。

socket网络编程接口

socket常用的一些接口(类似于文件操作)

底层:创建一个文件,打开网卡

domain(AF_INET/AF_UNIX):决定通信方式:本地、网络等

type(服务能力类型(数据包,流):决定使用网络协议种类,传输什么样的格式

SOCK_STRAM/SOCK_DGRAM),protocol(选择前两者,默认选择协议):决定以udp还是tcp通信,而服务能力类型决定了协议种类,因此直接写0。STRAM是TCP,DGRAM是UDP.

返回值(sockfd):网络的文件描述符,因此可以根据返回值用操作文件的方法,处理网络通信。

addr:绑定的套接字结构体类型。sockaddr_in(ipv 4 网络套接字结构体)

第一行:协议家族(将参数和协议家族结合成一个字符串),拼接通信方式的字符串,来决定结构体的通信方式

第二行:端口号 16位整型 因为在网络上给对方发消息,对方需要知道我的ip和端口,因此需要将端口号由本地转网络类型,而且需要进行大小端转换(htons),端口号不能随便bind,因为不同的端口号表示不同的服务

第三行:IP地址,其中in_addr是一个包含 32位的整型,因此传IP时要调用结构体成员。inet_addr

将点分十进制的字符串转换位32位整数,将这个整数转换为网络序列

注意:云服务器是应该虚拟化的服务器,不能直接bind公网ip,虚拟机可以bind自己的ip,可以进行bind内网IP,但只能在局域网中通信,因此只有绑定全0就可以都用。

小点:127.0.0.1 -》点分十进制风格的ip,特点:字符串类型,可读性好。 uin32_t ip -》整数风格ip-网络通信使用 特点:便于计算机内部使用

 

设计UDP:

server端的创建

void initServer(){ // 1.创建套接字 socket// 2.创建网络套接字的结构体  struct sockaddr_in ,然后对结构体初始化(bzero),填充// 3.将套接字绑定上ip和端口号 bind_sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd == -1)//判断创建成功与否{cerr << "socket error:" << errno << " : " << strerror(errno) << endl;exit(SOCKET_ERR);}cout << "socket success: " << " : " << _sockfd << endl;struct sockaddr_in local;//文件描述符绑定它的ip和端口,只定义了变量,在栈上面,属于用户,还不能进行网络通信bzero(&local, sizeof(local));                                    // 初始化local,全部变为0local.sin_family = AF_INET;                                      // 设置首两个字节决定它的套接字类型local.sin_port = htons(_port);                                   // 端口号的转入local.sin_addr.s_addr = inet_addr(_ip.c_str());                  // 将点分十进制转化为整型,以及本地转网络,这个ip用0.0.0.0是为了便于用于各种对这个服务器并且对应port发更加方便。int n = bind(_sockfd, (struct sockaddr *)&local, sizeof(local)); // 将网络套接字与网络文件的结构体绑定,这样就从用户转网络了if (n == -1){cerr << "bind error:" << errno << ":" << strerror(errno) << endl;exit(BIND_ERR);}}

recvfrom这类调用接口用于接收信息,其中的src_addr 输出型参数,用于了解谁发的消息的结构体

client端:

不需要知道的ip和端口,但是需要服务器的端口和ip,这样才知道发送请求给谁,需要知道服务器的公网ip。服务端需要显示bind的原因:需要显示bind端口,服务端需要明确的端口号,不能随意改变且众所周知的。客户端需要进行bind,但是不需要显示的bind,os会自动形成端口进行bind,原因:服务端是一家公司的,客户端是无数家公司。

TCP的实现

1.服务器创建文件描述符2.服务器绑定自己的IP和端口3.创建监听描述符4.客户端发起建立连接请求5.服务端接收连接6.服务端返回已经接收连接的回答7.客户端进行发送数据8.服务端接收数据9.开始通信

三次握手(建立连接)是os完成的申请连接,同意连接,回复接收到同意链接的回应,四次挥手(断开连接,双方都要提出)也是os完成的:1申请2单方面断联,2回复收到消息,2申请1单方面断联,1回复收到消息

accept:

参数sockfd:(用于监听) 获取新连接

返回值:用于与客户端通信,每次接收后,返回值都不一样,一个返回值对一个客户端,用于与客户端通信的套接字。提供玩服务后,需要关闭返回到套接字。

传输信息(面向字节流,类似于文件操作)

read(accept返回的套接字,字符串,大小):从文件中读取

客户端

先创建套接字,os自动bind。

connect(客户端套接字,服务端结构体,服务端结构体大小):对服务端发起连接,成功后返回值为0.

write(客户端套接字,字符串,大小):往文件里写入,通信手段,

须知:从输入流获取字符串getline(cin,字符串名称),读取整行文本,包含空格。cin>>读取无空格的单词,高效但忽略空格后的内容。fprintf(流,字符串):向流里面输入字符串,无缓冲,输出会立即显示,fflush(流)刷新流,保持流有新的输入,在多线程或复杂程序中显式刷新可以避免输出顺序混乱。fgets(字符串,字符串大小,流):从流中按行读取到字符串中,遇到\n就截止,但是如果从流输入换行符,字符串结尾会有一个换行符。

守护进程化(孤儿进程的一种)

xshell会给用户创建一个会话(其中右bash)属于前台任务(有且只有一个),任务由进程组完成的,sid属于这个会话的进程,这些进程可以前后台转换,jobs查编号,fg 编号切前台,ctrl+z切后台。这些进程,会受到用户的登陆和注销的影响,只有通过守护进程化自成会话,不受影响。

进程组:组长为第一个

守护进程化的接口:

setsid:创建一个新的会话,调用这个接口的进程不能是组长

步骤:

1.让调用进程忽略异常的信号:忽略管道退出命令

2.如何让自己不成为组长:通过子进程的方式,将父进程杀掉,然后调用setsid

3.守护进程脱离终端:/dev/null(文件黑洞),默认的操作所有进入的数据都丢弃,也读不到任何东西,打开dev,重定向dup2将0/1/2都重定向dev dup2(新,老)

4.进程执行路径发生更改 小点:进程存在一个cwd默认的指名在当前路径

套接字

分类:网络套接字(网络通信)、原始套接字(抓包) 、unix域套接字(本地通信)

套接字的结构体:第一个是模仿两者,设配后两者,第二个是网络套接字的结构体,第三个是域套接字的结果体,用前两个字节判断类型。

127.0.0.1:本地环回,本地的ip地址

云服务器是虚拟化的服务器,不能直接进行bind云服务器的公网ip,但可以绑定内网ip

如果将服务器的ip设置为0.0.0.0 就表明,接收所有想发个这个进程和端口号的客户端所发的报文(任意地址绑定),因为服务器中的进程可以绑定私有IP、公网IP等等,因此设为这个IP,就说明任意IP+端口号都可以发给它了,不在乎IP是多少。

netstat -nuap :查看网络进程的详细属性

mkfifo 文件名:创建命名管道,运用于文件与文件。

可以客户端输入的数据传到网络中,输出的数据重定向给管道。然后就会构成,客户端的收到的数据在管道中,可以对管道进行打印,而客户端发出的数据在网络中。

本地套接字的结构体创建和绑定,port和ip需要主机转网络,而收发不需要主机转网络,因为底层已经做好了。

协议定制

多个字符串组成的结构体类似于:头像,时间,昵称,消息 序列化 形成一个报文(字符串)。网络拿到报文,对报文进行结构化处理。

进行报文转换为头像,时间,昵称,消息叫做反序列化。

反序列化和序列化就是定制的协议

实现方法

先描述再组织,序列化通过结构体的方式,将这几点放入,然后转成字符串。反序列化是将字符串变成结构体。这个结构体的名称就是业务协议。

1.序列化过程的实现

2.反序列化过程的实现

3.业务协议的实现

4.保证报文的完整性

为什么需要序列化,因为容易出现问题,比如:内存对齐的问题。

tcp传输控制协议(需要序列化和反序列化,UDP收到的是完整的所以不需要):

应用层缓冲区的数据拷贝到tcp发送方的发送缓冲区,tcp接收方通过网络,将对方的数据拷贝到接受缓冲区。

序列化和反序列化的目的是因为在网络通信时,传一个长字符串很方便,便以理解,而其他的类型不方便传输。

接收缓冲区:根据定长,特殊符号

问题1:如何能保证收到的数据是完整的?

通过前缀,来获得具体信息的长度,引申出来的子问题(怎么知道前缀读完了)。

方法:因为收到的时候是用特殊的分隔符来隔开,将前缀转整型就是内容的长度。

我的问题为什么不直接通过分隔符来找到信息,而不要前缀?

在消息末尾添加特定分隔符(如 \r\n\r\n),接收方按分隔符切分消息。

缺点:数据内容若包含分隔符会导致误判;需遍历数据查找分隔符,效率较低。

在协议定制的头文件中要有,接收的类,发送的类,获取带报头字符串的函数,去报头获取正文的函数(用于接收的结果),对正文加报头的函数(用于接收结果后,处理完,进行回显的结果)。

问题2:如何将从命令行输入的内容,从客户端转换为带报头的字符串。

方法:设计函数,构建简易版本的状态机。原理:从命令行输入,用字符串接收,字符串提取,然后转整型 

以上的可扩展性比较差,怎么提高

系统自带的序列化和反序列化的用法:Json

JSON::Value 接收后各种类型

value是一个pair

序列化 json::fastwriter/styledwriter

 write返回值就是序列化后的值

反序列化json::Reader

parse提字符串的值

如何在一套代码中定制多种协议,以及如何让系统知道用哪一个协议

字符串长度/分隔符/协议编号/分隔符/内容

会话层连接管理,表示层数据转换序列化和反序列化,应用层约定协议定制

HTTP:应用场景:web

概念:通过HTTP可以将服务器的网络资源拿给客户端

URL:俗称网址,获取网络资源

端口号:会被统一做管理,指定的用途

utlencode和urldecode

作用:前者将客户端的符号进行转化为url中的特定格式(编码),后者将url格式转换为符号(解码),目的:不干扰对url的解析,影响获取资源的操作。

编码规则:

  • 非保留字符保留原样。

  • 保留字符若在非保留位置出现(如查询参数中的/),需编码。

  • 其他字符按指定编码(如UTF-8)转为字节序列,每个字节转为%XX(十六进制)。

encode实现:

#include <string>
#include <iomanip>
#include <sstream>// 判断字符是否需要保留原样(非保留字符)
bool is_unreserved_char(char c) {return (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~');
}std::string url_encode(const std::string &value) {std::ostringstream escaped;escaped.fill('0');escaped << std::hex;for (auto c : value) {if (is_unreserved_char(c)) {escaped << c;} else {escaped << '%' << std::setw(2) << int(static_cast<unsigned char>(c));}}return escaped.str();
}

decode实现:

#include <cctype>std::string url_decode(const std::string &value) {std::string result;result.reserve(value.size());for (size_t i = 0; i < value.size(); ++i) {if (value[i] == '%') {if (i + 2 < value.size()) {// 提取十六进制字符并转换为字节std::string hex = value.substr(i + 1, 2);char decoded = static_cast<char>(std::stoi(hex, nullptr, 16));result += decoded;i += 2;} else {// 无效的 % 格式,跳过result += value[i];}} else if (value[i] == '+') {// 查询参数中的 '+' 转为空格result += ' ';} else {result += value[i];}}return result;
}

http的请求格式:

申请版本:目的是申请到对应版本的服务器,根据版本给相应的服务

http的回复格式:

协议版本:http 1.0 1.1 2.0这种作为第一行的内容

状态码:判断请求的状态,例如:404

状态码描述:对状态码进行解释意义

http是在应用层对数据做到结构化处理后的协议规则,规定了传输的格式,而tcp和udp在传输层是做传递具有这些协议规则的数据。

http应用层读取完整请求和响应的方法

1.因为换行符存在的原因,就可以读取完整的一行

2.循环读每一行,直到空行

3.报头可以全部被读完,报头有正文长度,因此根据报头可以读取完整的正文。

4.正文数据通过读取文件内容来获取

http请求和响应的序列化和反序列化

按照\r\n进行字符串转换为多行内容

HTTP 

http设计步骤:

先写出了服务端对数据处理的每个操作,然后根据每个操作去设置函数和类,第一步是接收数据,第二部反序列化(请求类),第三步回调函数(执行任务函数),第四步序列化(回复类),第五步回复。

客户端不用实现,因为计算机自带的浏览器就已经是一个已经做好的客户端。

客户端发送给服务端的请求:

服务端对请求的分割处理:

要点:需要与HTML结合进行回复,前提是分割得到响应的HTTP的请求格式,根据请求格式回应相应的网站给客户端。

小点:telnent 127.0.0.1 端口号 可以在linux中查看服务器的状态。浏览器现在已经很成熟,可以不对回复进行反序列化,就可以处理回复消息了。

就是web服务器中有根目录,服务器所在根目录下

web服务器中可以进行配置路径,index.html(默认首页)

可以设置从哪个文件夹/文件下面找指定的资源

根据资源不同,就需要标定不同的响应报头。然后用资源的后缀去映射响应报头,客户端请求资源会有路径,根据路径分离后,找到后缀,然后找到资源。

手动设置路径的目的:

  1. 统一访问入口:用户输入域名即可直达首页(如http://example.com自动访问index.html),无需输入完整文件名。

  2. 安全防护:避免服务器暴露目录结构(如访问/images/时不返回文件列表),提升安全性。

  3. 灵活适配:不同子目录可定制独立默认页(如/blog默认显示博客列表),适配复杂结构。

  4. 环境一致性:开发、生产环境可统一配置默认文档,避免因服务器默认规则差异导致问题。

http请求方法

需知:表单,目的是客户端向服务端提交数据,例如:账号登陆。前端在网页上提交表单,后端就会收到内容,进行处理,解析为GET或者POST。

请求方法:GET.

操作:将网页形成的参数,以url的方式直接拼接到当前ip和端口号后面,提交给服务端。

缺点:不私密,不安全,不能接收大的参数,因为url。

请求方法:POST

操作:将网页形成的参数,通过http请求的正文提交参数。

优点:私密性好,传递参数可以很大,因为在正文。 缺点:不安全

通过方法可以进行分离客户端提交的数据,按照访问路径,进行绑定服务,进行执行其它任务,跳转网页等。

状态码:

4开头为客户端的错误,访问的资源一般,服务端提供不了这类资源

5服务器一般是创建空间和创建线程出错

3重定向(301,307,308)进入网站会跳转到其它网页

307/302临时重定向:类似于跳转到广告商

301永久重定向:网站升级后,访问原始网站每次进入就会跳到新网站,更新本地书签。

HTTP常见的一些报头

Content-Type:数据类型

Content-Length:body的长度

Host:客户端告知服务器,所请求的资源是哪一个主机的那个一个端口上。

user-Agent:客户端的设备信息,服务端可以根据设备信息,去回复客户端,这就是pc和手机端的网站不同的原因。

Accept:客户端告诉服务端,客户端可以接受什么格式。

location:搭配3开头的状态码。告诉客户端接下来要去哪里访问。

HTTP的一些关于网站的知识点

长链接

作用是获取一大份资源,通过一条链接就可以完成,因为http是基于tcp的,然后面向链接会频繁的创建链接,所以长连接可以解决建立链接的成本。

会话保持

保持用户始终在线,切换页面不影响之前的操作和登陆

身份认证:凡是对于网页有权限要求的网页,在被获取之前,全部都要做判断。

如何实现会话保持

浏览器存用户登陆的信息是用cookie文件存的,因此每次关闭还有用户信息,如果关闭浏览器进程需要重新输入,说明是cookie文件内存存的

木马是:获取用户信息,对计算机没有影响,盗取cookie文件,泄露账号密码

解决方法:通过登陆方法将用户的认证信息和浏览痕迹不保存在浏览器端,而是保存在服务器端,用session id来唯一标识,然后返回session id 给浏览器,浏览器只保存seesion id(本地cookie文件),浏览器拿seesion id 就可以拿用户的数据。

如果黑客拿到session id 进行访问,如何进行避免

用一定策略,让session id失效即可,比如(ip地址的网络号突然改变)

实操问题:服务器如何写入cookie信息,如何进行验证

响应报头设置cookie后,以后每次客户端http请求,会自动携带曾经设置的cookie报头,帮服务器进行鉴权,会话保持

基本工具

postman:模拟客户端--浏览器的行为,

fidder:抓包工具--主要抓http的工具,抓本地请求的http,主要用于调试,相当于中介

HTTPS

根据端口可以区分两者,http80,https443,就是在http协议的基础上引入了一个加密层.目的是结局传输安全的问题(数据篡改,数据被窃取)。

原理: 底层用密钥对数据加密,接收方拿到密钥进行解密

 常见的加密方式
哈希摘要

session id 就是经过哈希摘要形成的,哈希摘要的搜索作用:对文件进行哈希形成摘要,保存在服务端,如果不同的客户端要对相同的文件进行存服务端,服务端会对这个文件进行哈希摘要,得到的字符串,直接在服务器中寻找,如果有直接在服务器中形成软连接,这样两个在不同的本地文件,在服务器里就变成了一个。

http的加密方法选择

对称加密(密钥相同):黑客拿到数据,不知道密钥是什么也没用,但是服务器和客户端需要看到同一份密钥,这之间也需要传递,所以黑客也会拿到未加密的密钥。因此密钥也需要被安全传递,所以密钥也要有密钥的密钥,因此这个对称加密操作并不安全,解决不了http的安全需求。

服务器非对称加密(密钥不同):公钥(客户端都有,公开的)加密,私钥解密,私钥加密,公钥解密,服务器形成私钥和公钥,客户端第一次握手,服务端第二次发起握手推送公钥,客户端用公钥加密数据,第三次握手发送加密的数据,服务端拿到数据后,用私钥解密,但是服务器恢复数据,用私钥加密就不安全了。

双方非对称加密:原理用各自发来的公钥加密,自身用私钥解密。缺点:慢,有安全问题()

非对称+对称加密:客户端发起请求,服务端应答以及接收链接请求并且传递公钥给客户端,客户端生成对称密钥,用公钥加密密钥,传给服务端,之后用对称密钥通信,与双方非对称密钥类似,只是要快一点。

以上的方法都会遇到一个问题:

中间人攻击:在最开始协商,三次握手时,它就进入传输路径上,获取各种信息包括密钥,然后中间人此时就相当于一个客户端了,每次信息都要经过中间人,再到客户端,中间人就可以有自己的公钥和私钥,将在自己的密钥给客户端,将服务端的密钥给自己,自己来做信息转发。

如何防止中间人对传递公钥处理

证书:数据签名(非对称加密算法),生成哈希散列值,防止数据篡改

数据签名:对数据通过哈希摘要形成散列值。

CA证书,非对称,对称相结合。

CA机构有自己的公钥和私钥,CA公钥内置在浏览器中。

第一步:CA对服务端提交来的数据(服务端形成的公钥,服务端信息)进行哈希摘要得到哈希散列值。

第二步:CA用自己的私钥(CA独有)加密散列值(数据签名),CA将数据与加密的散列值合起来,形成CA证书。

第三步:证书返回给服务端,服务端将证书和应答推给客户端。

第四步:客户端收到证书,客户端用浏览器中CA的公钥将数据签名解开,然后分离数据签名和明文数据。

第五步:将数据(服务端形成的公钥,服务端信息) 进行哈希摘要,得到对应的散列值,然后与数据签名对比,如果一样说明公钥没有被篡改,不一样说明公钥被篡改了。

第六步:客户端再进行生成对称密钥,然后用服务端的公钥对对称密钥加密,传给服务端,服务端用私钥进行解密拿到对称密钥。

第七步:双方用对称密钥通信。

注意:期间中间人只能拿到服务端的公钥,但是公钥只能加密,无法解密,因此无法查看信息。如果中间人对CA证书进行更改,将CA中服务端的公钥改了,就无法与数字签名匹配,如果两个都更改了,用自己的私钥对数字签名加密了,但是浏览器中内置的CA公钥是打不开这个数字签名的,因此也无法更改成功。注意的要点CA的公钥只能解密,服务端的公钥只能加密。

因为加密哈希散列值是为了浏览器用固定的公钥解密,相当于匹配一样,如果不进行加密,浏览器就无法判断这个数据签名是是不是CA形成的,这样中间人就可以篡改公钥和数据签名了。也就是,不进行加密,中间人就可以自己形成一个证书了,客户端浏览器还不能验证是否是安全的。

传输层

再谈端口号(linux内核下是16位)

端口标识应用层中不同的应用程序,例如0-1023应用于知名协议,HTTP-80 

进程与端口号的关系:一对多,一对一

指令:

pidof :得到进程的pid, pidof 进程 | xargs(从管道得到pid,放在命令行后面)

netstat :

语法 -选项 :-l 处于监听状态  -n 协议数字化显示 -t tcp  -p 进程信息 -u udp

UDP协议

报头:固定8字节,用于定制数据的大小。本质是一个结构化数据对象。操作:先进行开空间,将结构体和有效载荷结合,然后强转成结构体,填入数据,传字符串数据到别的os上,然后进行强转为结构体数据,就可以拿到报头的信息了。

源端口:发送数据报的应用程序所使用的端口。

目的端口号:匹配上层的应用的端口号,用于交付给上层的应用,进行分用。

UDP长度:整个UDP长度(报头和数据),最大64KB,超过了需要进行打包分开发。

校验值:检验数据再传输过程中是否损坏

基于UDP协议的应用层协议:NFS TFTP DHCP BOOTP DNS 

特点:

无连接:知道对方的ip和端口号,可以直接传输

不可靠:没有确认机制,没有重传机制,不用管数据是否发给对方,发了之后就不管了

面向数据报:直接能读完一个完整的数据报,·不用考虑读不完一个数据报。

缓冲区:接收接口要经过接收缓冲区,只有接收缓冲区,因为,可以实现类似于消费者和生产者模型,让进程执行其它任务,而因为不需要可靠性,所以发送直接调用接口经过网络直达对方接收缓冲区

TCP协议

两种工作模式 c->s:

一端发送一条,一端应答一条

一端并发发送多条,一端并发回复多条

报头

不加选项标准20个字节的大小,结构化数据

源端口:发送数据报的应用程序所使用的端口。

目的端口号:匹配上层的应用的端口号,用于交付给上层的应用,bind就是添加到哈希表中,通过haxi的方式找到进程的PCB,进行分用。

4位首部长度:加上选项的报头长度[0,15],报头总长度=首部长度*4字节

序号:标识发出数据的顺序序号,类似于数组下标。

确认序号:用于应答的报文中,对应发来的报文的序号,让对方下一次开始的序号是多少,

对发来的报文序号+1。

小点:两个序号存在的条件是因为,两端都有发送和接收所以要有自己的标识序号

窗口大小:告诉对方自己接收缓冲区剩余大小,对方可以根据这个进行流量控制。

标志位(1/0控制)【标识报文的类型】

URG:tcp的数据是按序到达,如果有数据的紧急指针标志位1,有效载荷中包含了需要被特殊尽快的数据(用16位紧急指针作为偏移量去有效载荷找这块数据,这个数据是一个字节),就可以进行插队,优先处理,用于发带外数据。将紧急数据跳过接收缓冲区队列,直接提交给上层应用进程处理,而普通数据仍按正常流程缓存或处理。

ACK:确认收到1,用于这个报文是否为确认的报文

PSH:定期催促接收方上层取走接收缓冲区的资源1,让read和write的读取条件满足

RST:复位标志位1,单方面认为连接不存在时,用这个标志位告诉对方,进行连接重置,通常用于连接建立后,某一端出问题断开了连接,然后另一端一直发报文。

SYN:建立连接1  

FIN:断开连接 1

特点

1.全双工,一个接收区,一个发送区

2.可靠性传输:发消息之后,对方对收到正确的旧消息有应答

3.字节流

4.面向连接

超时重传机制(TCP策略,超时(根据网络情况决定的))

作用:用于处理丢包问题(数据丢了,应答丢了),设置一定时间,如果超过一定时间没有收到对方应答就会重传数据,而这个数据会保存在发送缓冲区里一段时间,之后会被新数据覆盖。如果接收方收到重复的数据,tcp会根据序号自动丢弃收到的重复的数据。

超时时间:根据网络的质量进行浮动变化的。一般以500ms为单位,时间是它的整数倍。

连接管理机制

一次握手的缺点:多个客户端发起建立连接,就会单方面对服务端形成洪水攻击,而客户端没有资源损失,服务器缺一直有连接请求,消耗它的资源。

两次握手的缺点:跟一次握手一样,因为服务端的连接建立成功的回复会丢失,然后客户端还是会洪水般的发起请求,因为他不知道连接建立成功没有。

 三次握手是建立连接机制,不保证三次握手成功.(握手期间可能会出现SYN的消息丢失)

三次握手优点:

1.用最小成本验证全双工通信时通常的。验证方法:全双工的功能是能发能收,两次握手能够知道客户端能发能收,服务端则只知道能收,能发需通过要第三次握手的客户端应答证明。

2。可以有效防止单机进行对服务器进行攻击。防御的核心思路是:减少服务器在握手完成前需要消耗的资源,或者更早地识别并丢弃恶意SYN包。

三次握手的目的:

第一次:请求连接,发送带有syn标志位的报头。

第二次:同意连接,采用带有syn和ack的报头回复,此时请求方先建立成功。

第三次 :收到请求方连接建立成功的ack应答报头,这时接收方再建立成功连接。

这三次握手:实现了以最少次数使双方都完成连接,间接保证了可靠性,因为报文内部有一些数据,两端根据握手的报文内部数据,进行用户数据的传递,建立器连接结构体。

四次挥手

第一次挥手:客户端发送单方面FIN(断开连接),之后不给服务端发用户数据了,但是还有底层报文数据。

第二次挥手:服务端对客户端单反面断连应答

第三次挥手:服务端对客户端也进行单方面断连

第四次挥手:客户端对服务端单方面断联进行应答,这是底层报文数据,不属于用户数据。

四次挥手两端的状态:

1.断开连接是双方都能发起

2.第一个发送断连的状态是FIN_WAIT_1,而回复端进入CLOSE_WAIT 

3.第二个发送断连的进入LAST_ACK,而回复端为TIME_WAIT

4.服务端调用close关闭文件描述符后,会发出FIN给客户端,客户端就会发ACK进行应答,如果服务端没有收到客户端的ACK回复,它就不会断开,会进行补发FIN,因此客户端会处于一段时间(2*MSL)的TIME_WAIT。

TIME_WAIT(2倍MSL:两次收发所花的时间,报文生成时间) :是为了防止最后一次服务器没收到ACK,为了让对方去补发FIN,所以会等待一段时间,保证ACK被对方收到,防止滞留报文

立即重启服务端

服务崩掉之后,短时间无法重新bind套接字。

int setsockopt(SOCKET s, int level, int optname, const char FAR *optval, int optlen);
流量控制

报头中的窗口大小就是为了流量控制,通过连接发报文时,在报头中携带自己的窗口大小,让对方根据窗口大小,用相应的速度来传递相应大小的数据。

滑动窗口

本质:基于可靠性,为了提高发送效率,可以并发

发送方的发送缓冲区存在滑动窗口,滑动窗口根据接收方接收缓冲区大小而定的。滑动窗口的前方为已经发送的数据并且收到对方应答,而滑动窗口是发给对方了,还没收到应答。

滑动窗口的原理

1.它是按序号进行发送给对方,类似于数组下标。

2.当发给对方后,并且收到应答,begin会向后移动,begin=确认序号。

3.当发给对方后,收到应答,并且应答中包含对方取走缓存区数据后的新的窗口大小时,end会向后移动,end的位置为begin+对方剩余窗口大小。

4.对方每次的应答是接收到数据的序号+1,告诉发送方下一次发的数据序号应该从这个数字开始。

5.如果对方接收到的数据序号不能连接起来,说明中间发送的数据有丢失情况,因此连续收到的数据都会应答相同的序号,这个序号是丢失数据的前一项没有丢失数据下标+1。

6.如果发送端接收到三次次相同序号,这是发送端就会按这个序号开始,进行重发。

7.发送缓存区的数据满了,数据会重开头进行覆盖已经发送并且收到应答的数据,类似于环形结构。

8.如果应答丢失了,不会受到影响,因为下一次应答的序号还是会按照本来的规则进行,不会进行重发。

拥塞控制

大背景就是网络问题,停止重发

拥塞窗口

恢复网络过程中,采用指数级的慢启动,其中会引入阈值,来规定达到这个阈值后,开始加法增长,拥塞窗口根据阈值变化。

滑动窗口大小=min[拥塞窗口,对方窗口]

延迟应答:因为有确认序号,所以可以对多个报文一起确认应答,这样可以先收多个数据,再一起应答,这样可以提高效率。

捎带应答

面向字节流:

字节流是什么?

  • 面向字节流(TCP):像用水管传输水,水流连续不断,你无法区分哪滴水是哪个杯子倒进去的。

  • 面向数据报(UDP):像用快递寄包裹,每个包裹独立打包,贴上地址,彼此之间毫无关联。

维度面向字节流面向数据报
数据组织连续字节流,无边界。独立数据包,有明确边界。
传输控制可靠、有序、流量控制。不可靠、无序、无流量控制。
适用场景大数据量、高可靠性需求。低延迟、容忍丢包、简单请求-响应。
协议代表TCP、SCTP(支持多流)。UDP、ICMP。

粘包问题

概念:

解决方法:

listen第二个参数

网络层

IP:将数据从主机a跨网路到主机b的能力

功能:路径选择:什么最重要,功能是选择数据传递的路线。

IP的组成:   网络地址+主机地址                                 举例:     

IP协议的协议报头结构:

4位版本:Ipv4或ipv6,IP的长度

4位首部长度:单位4字节,是报头长度 类似于TCP,要对长度*4.

16位总长度:报头+有效载荷的长度                            作用:得出有效载荷长度

8位协议:用于给上层,给到传输层的具体协议         

16位首部校验和:检验数据是否损坏

8位生存时间:传递的步长,需要经过多少ip,到达目的ip的主机。如果没有在指定步长完成,就会销毁重发              产生的原因:防止循环转发,导致一直没发送到指定位置。

32位源IP地址:发送端的网络层分配的主机IP

32位目的IP地址:接收端的IP

传输过程经过的结构和过程:例子(归还钱包)

主机:发送端和接收端

子网:发送端和接收端所在的区域,可以通过区域找到各自主机。

主机与子网的关系:子网里面包含主机,由多个主机进行构成,而这些主机是消息互通的。

路由器:每个子网都有一个路由器,而路由器就是对子网的数据进行管理。然后每个子网的路由器又在更大的子网中进行消息互通。

子网划分

子网划分方法:通过网络号进行划分,每个子网网络号不同,子网内部主机号不同,而主机号对于子网外部的其他子网的来说可以相同。   

子网划分目的:解决IPV4的32位地址不够用的问题。

划分的类型:

ABCDE子网划分:缺点是有些网络不需要太多主机,但是却分配了大量的主机ip就会引起一些ip没被使用。

动态地址分配:在子网内部,一些设备下线之后,可以把这个ip给其他主机。

公网和私网:通过子网掩码的方式进行分配私网ip。

NAT:私有IP可以重复,出公网IP进行通信时,转化为公网IP。

IPV6:采用128位IP地址。

公网和私网:内外网协同

公网:ICANN分配—运营商获取—用户使用

特殊地址:
  127.0.0.1:本机环回(自己寄信给自己)  
  169.254.x.x:DHCP失败时自动分配(无家可归的临时地址)

策略:主机采用内网ip,路由器采用内网加公网ip,内网用于内部,公网用于路由器所属的更大的网络中,一层套一层。

子网IP:

WAN口IP:

私网

私有IP:

传输过程:主机的在局域网中对比路由表,进行跟子网掩码的与运算,寻找指定的目的ip,如果没有就跳出这一层局域网,往更上一层,用同样的方法寻找。

路由表:涵盖连接路由器下,所有的IP地址。

路由转发:主机构造IP数据包,通过路由表寻找,如果有在局域网下,所有主机进行解封至IP层,对比目的IP,找到确定的主机,没有满足的就通过发送给网关。

网络层对数据的处理

这三个的作用

16位标识:用于将数据匹配数据链路层大小进行分片,这个是分片之后,所属同一报文的身份证号。

3位标志:第一位1表示还有分片,0表示最后一片

13位片偏移:每个分片距离第一个分片的地址的距离。

数据链路层:协议:以太   功能:与传输层相关,规定数据一次传输的大小

IP的分片和组装:                  

目的:分片为了满足数据链路层的要求。

组装的方法:

1.识别是否为分片:通过13位偏移和3位标志位

2.识别同一个分片:16位标识符

3.检测分片的完整和第一个以及最后一个:通过组合之后,13位偏移能够组合起来,连接上就是一个整体,第一个是偏移量0,最后一个有偏移量且标志位为0

4.正确顺序组装分片:根据偏移量来排序

5.保证报文内部数据是否正确:IP和TCP都有校验码。

分片好吗?

对tcp和udp ip的影响

分片方法

通过加报头,然后填写标识符,标志位,偏移量,然后满足链路层的数据要求。

数据链路层

局域网下转发原理:

以太(ether)网协议:MAC指针做报头

MAC的分离

目的地址:目标主机的MAC地址(全球唯一网卡标识)

源地址:当前主机的地址

类型:

CRC:差错检测

MAC的分用

基于以太网的局域网转发:

同一个路由器下,消息互通,发消息给局域网内部任意一个主机,所有主机都会拿到,然后进行检测,不符合就丢弃。

局域网的通信规则

规则对应的策略(局域网类似于临界资源)

局域网内部通信只能一个一个发,类似于管道,有一个主机拿到令牌才能发,其余等待,如果等待时间相同,会发生碰撞,此时可以用交换机来隔离碰撞域,定向转发,如果遇到碰撞,都停止,然后不处于碰撞域的进行发送。

交换机

相关文章:

  • Vue-2-前端框架Vue基础入门之二
  • 《深度解构现代云原生微服务架构的七大支柱》
  • 儿童节快乐,聊聊数字的规律和同余原理
  • C++代码常见问题解析与优化(虚函数)
  • 从架构视角设计统一网络请求体系 —— 基于 uni-app 的前后端通信模型
  • 【设计模式-3.4】结构型——代理模式
  • QT-JSON
  • B站视频下载器 v1.0.4|免登录下载1080P视频
  • LabVIEW双光子显微镜开发
  • C++四种类型转换方式
  • 017搜索之深度优先搜索——算法备赛
  • 宝塔专属清理区域,宝塔清理MySQL日志(高效释放空间)
  • Azure Devops 系列之三- vscode部署function app
  • LeetCode算法题 (搜索二维矩阵)Day18!!!C/C++
  • 李臻20242817_安全文件传输系统项目报告_第14周
  • 力扣面试150题--二叉树的锯齿形层序遍历
  • 自动驾驶系统研发系列—激光雷达感知延迟:自动驾驶安全的隐形隐患?
  • AWS之数据分析
  • 【科研绘图系列】R语言绘制论文组合图形(multiple plots)
  • AWS之迁移与传输服务
  • 公安局网站备案流程/爱站seo查询
  • 温州网站上排名/百度关键词搜索技巧
  • 微信分享网站怎么隐藏域名/百度推广官网电话
  • 仿牌外贸网站制作/百度app下载官方免费最新版
  • 想在网站里添加超链接怎么做/软文营销实施背景
  • 电子商务网站建设包括哪些内容/站长工具站长之家