Linux - 应用层HTTPS、传输层TCP/IP模型中典型协议解析

目录

  • 应用层:
    • 自定制协议
      • 实例
    • HTTP协议
      • 首行
      • 头部
      • 空行
      • 正文
      • http服务器的搭建
    • HTTPS协议
  • 传输层
    • UDP协议
    • TCP协议

应用层:

应用层负责应用程序之间的沟通—程序员自己定义数据的组织格式
应用层协议:如何将多个数据对象组织成为一个二进制数据串进行传输
需要考虑的要素:传输性能,解析性能,调试便捷性

序列化:将数据对象按照指定协议进行组织成实现持久化存储或者网络通信传输的二进制数据串的过程
反序列化:按照指定协议,将二进制数据串解析得到各个数据对象的过程
序列化方式:结构体二进制序列化、json序列化、protobuf序列化

自定制协议

自定制协议:程序员自己定制数据格式

实例

网络版计算器:
客户端将两个数字,以及运算符,传输给服务端
服务端对数据进行运算,将结果返回给客户端
具体结构在上一篇博客套接字部分,这里只是讲自定制协议

1.首先在tcpsocket头文件里面自定义数据格式

struct data_t
{int num1;int num2;char op;
};

2.在tcp_cli客户端收发数据部分进行发送与接收

//4.收发数据struct data_t tmp;tmp.num1 = 11;tmp.num2 = 22;tmp.op = '+';//方法一:调用自定义函数//std::string buf;//buf.resize(sizeof(struct data_t));//memcpy(&buf[0], &tmp, sizeof(struct data_t));//CHECK_RET(cli_sock.Send(buf));//buf.clear();//CHECK_RET(cli_sock.Recv(&buf));//std::cout << *(int*)buf.c_str() << std::endl;//方法二:int fd = cli_sock.GetFd();send(fd, (void*)&tmp, sizeof(struct data_t), 0);int result;recv(fd, &result, sizeof(int), 0);std::cout << result << std::endl;

3.在tcp_srv服务端收发数据部分进行接收与发送

//5.收发数据    --使用获取的新建套接字进行通信int fd = clisock.GetFd();struct data_t tmp;recv(fd, &tmp, sizeof(struct data_t), 0);int result;if(tmp.op == '+'){result = tmp.num1 + tmp.num2;}else{result = 0;}send(fd, &result, sizeof(int), 0);

HTTP协议

HTTP协议:超文本传输协议
http协议格式:http的协议实现,http协议的数据结构
首行:请求行,响应行(对于请求与相应的简单关键描述)
头部:对于请求或者响应或者正文的一些关键描述
由一个个键值对组成key:val, 每个键值对以\r\n结尾
空行:\r\n,间隔头部与正文;\r\n\r\n – 头部结尾
正文:客户端提交给服务端,或者服务端响应给客户端的数据

首行

-请求行:请求方法,URL(URI),协议版本\r\n

请求方法
GET:从服务器获取实体资源,请求没有正文,但是也可以提交数据,但是提交的数据没有在正文中而是在URL中
1.get提交数据不安全;2.URL长度有限制
HEAD:功能与GET类似,但是不要正文实体
POST:向服务端提交数据,请求有正文,数据放在正文中

URL:网址–统一资源定位符–用于定位网络中某个主机上的某个资源
组成:协议名称://用户名:密码@域名:端口/资源路径?查询字符串
https://user:password@www.baidu.com:80/s?ie=utf-8&wd=ASCII
域名:服务器别名–最终访问服务器需要经过域名解析得到服务器IP
资源路径:这个路径是一个相对根目录
查询字符串:提交给服务器的数据,由一个个key=val形式键值对组成,键值对之间以&符号间隔
urlencode:编码-用户请求的资源路径,或者查询字符串中存在特殊字符,则有可能与url中的特殊字符冲突;将特殊字符每个字节转换为16进制数字字符,并前缀%
urldecode:解码-遇到%则认为紧随其后的两个字符进行了编码,将这两个字符转换为数字,第一个数字左移4位加上第二个数字

协议版本:0.9,1.0,1.1,2
0.9:最早期版本,只支持GET方法,并且协议还没有当前的规范,只支持超文本数据传输。
1.0:规范了http协议格式,并且新增支持GET,HEAD,POST请求方法支持各种多媒体资源传输,简单的缓存控制。
1.1:更多的是对1.0版本进行性能的优化,支持了更多请求方法以及特性(支持长连接,更加完善的缓存控制,分块传输…)
2.0:因为http协议的庞大冗余,因此2.0不是新增特性,而是重新定义http协议①使用二进制数据传输;②支持主动推送资源;③服务器进行长连接响应,不需要按序进行

Connection:用于控制长连接的打开关闭状态 keep-alive/close

-响应行:协议版本,响应状态码,状态码描述\r\n

响应状态码:直观向客户端反馈处理结果
1××:一些描述信息;101-协议切换状态码
2××:表示本次请求正确处理;200
3××:重定向-表示本次请求的资源移动到了新的链接处,并且原链接依然可用;301/302
4××:表示客户端错误;404
5××:表示服务器错误;500-服务器内部错误;502-代理服务器没有收到正确响应;504-超时
状态码描述:就是针对状态的文字描述

头部

头部:关于请求或者响应,或者正文的一些描述字段
组成:key:val\r\n key:val\r\n
典型头部字段
Connection:长短连接控制;keep-alive/close
Referer:记录本次请求的来源链接
Content-Type:用于表示正文的数据格式
Content-length:用于表示正文的长度–http解决粘包问题的关键字段
Location:用于指定重定向的新链接地址,与3××搭配使用
cookie与session:涉及的头部字段请求头Cookie,响应头Set-Cookie
http协议是一个无状态协议
1.一个客户端登陆之后,服务端验证登录,成功后,通过Set-Cookie字段设置cookie信息(用户信息,状态…)返回给客户端
2.客户端收到响应后,将Set-Cookie字段的cookie信息保存起来,下次请求服务器的时候从cookie文件中读取出cookie信息,通过Cookie字段发送给服务器。
cookie是一个维护http通信状态的技术–但是存在安全隐患。
解决方案:session
session是服务端针对每个客户端所建立的会话,当客户端登录成功后,创建会话,在会话中记录客户端用户信息以及状态…,通过Set-Cookie字段将session_id返回给客户端
session_id每次请求都会发生变化,并且用户的隐私信息一直保存在服务器防止泄露。
cookie与session的区别
cookie是维护http通信状态的技术,将关键信息保存在客户端,每次请求服务器时,读取出来发送给服务端(存在安全隐患)
session是解决cookie安全隐患的技术,将关键信息保存在服务器,将sessionid发送给客户端,作为cookie保存起来,解决了cookie泄密的风险。

空行

空行:\r\n
是与头部最后一个字段的结尾\r\n组成连续的\r\n\r\n作为特殊标志
作为http头部结尾的标志

正文

针对不同的传输所提交的数据或服务端响应的数据,以什么格式我们自己来定。

http服务器的搭建

http是一个应用层协议,只是应用程序如何沟通的一种数据格式约定,在传输层是基于tcp实现的 http客户端实际上就是一个tcp客户端;http服务器实际上就是一个tcp服务器,只不过http客户端与服务端的通信使用的是http协议来约定数据格式而已。
简单的http服务器的搭建:
1.搭建tcp服务端
2.获取新建连接
3.使用新建连接,等待接收数据(http协议的请求数据)
4.接收过程:先接受http头部,解析头部-Content-Length确定正文长度
5.接收指定长度的正文
6.根据请求方法以及资源路径确定客户端的请求目的
7.进行具体对应的业务处理
8.组织http协议格式的响应数据,对客户端进行回复
9.如果是短连接,则直接关闭套接字,如果是长连接,则继续等待接收数据


#include "tcpsocket.hpp"
#include<sstream>int main(int argc, char *argv[])
{//通过程序运行参数执行服务端要绑定的地址//./tcp_srv 192.168.2.2 9000if(argc != 3){printf("usage: ./tcp_src 10.106.200.199 9000\n");return -1;}std::string srvip = argv[1];uint16_t srvport = std::stoi(argv[2]);TcpSocket lst_sock;//监听套接字//1.创建套接字CHECK_RET(lst_sock.Socket());//2.绑定地址信息CHECK_RET(lst_sock.Bind(srvip, srvport));//3.开始监听CHECK_RET(lst_sock.Listen());while(1){       //4.获取新建连接TcpSocket clisock;std::string cliip;uint16_t cliport;bool ret = lst_sock.Accept(&clisock, &cliip, &cliport);if(ret == false){       continue;}
//------------------------------------------------------http服务端接收数据----------------------------------------------std::string buf;clisock.Recv(&buf);std::cout << "request:[" << buf << "]\n";std::string body = "<html><body><h1>Hello ysy</h1></body></html>";std::stringstream ss;//首行ss << "HTTP\1.1 200 OL\r\n";//头部ss << "Connection: close\r\n";ss << "Content-Length:" << body.size() << "\r\n";ss << "Content-Type: text/html\r\n";//空行ss << "\r\n";//正文ss << body;clisock.Send(ss.str());clisock.Close();
//------------------------------------------------------http服务端接收数据----------------------------------------------}//6.关闭套接字lst_sock.Close();return 0;
}

注意:http服务器编写完毕之后
云服务器:记得设置安全组策略,开启对应端口
虚拟机:记得关闭防火墙 sudo systemctl stop firewalld

//302重定向std::string buf;clisock.Recv(&buf);std::cout << "request:[" << buf << "]\n";std::string body = "<html><body><h1>Hello ysy</h1></body></html>";std::stringstream ss;//首行:302重定向ss << "HTTP\1.1 302 OL\r\n";//头部ss << "Connection: close\r\n";ss << "Content-Length:" << body.size() << "\r\n";ss << "Content-Type: text/html\r\n";//重定向ss << "Location: http://www.baidu.com\r\n";//空行ss << "\r\n";//正文ss << body;clisock.Send(ss.str());clisock.Close();

HTTPS协议

HTTPS协议:并不是一个新的协议,而是在HTTP协议基础上进行了一层加密
https协议就是基于ssl进行加密实现加密传输
HTTPS=HTTP+SSL
目的:实现数据的安全传输
安全传输:需要考虑两个问题
1.身份验证问题:防止伪装
2.数据加密问题:防止监听

身份验证实现
原理:使用第三方权威机构进行身份验证(CA证书)
CA认证:通信双方在通信前先到权威机构请求给自己颁发一个CA证书。CA证书(权威机构信息,自己的信息,…),通信两方建立连接后,在通信之前先将证书发送给对方,收到对方的证书后,查看这个权威机构是否是自己新人的权威机构,如果是,则到权威机构进行这个公司的身份验证。验证通过后进行通信,不通过可以自行选择是否添加信任。
身份验证通过,但是通信依然有可能被监听,存在风险,因此需要加密传输。
加密传输实现
①.对称加密:加解密使用相同的秘钥。
优点:加解密效率高
缺点:秘钥一旦被劫持则加密形同虚设
②.非对称加密:加密和解密使用不同的秘钥
思路:通信中,每一端在通信前都可以生成一对秘钥(公钥和私钥),在通信前,将公钥发送给对方,对方使用收到的公钥进行加密数据然后传输,自己收到数据后,使用私钥进行解密。
实现算法:RSA加密算法
优点:安全度更高
缺点:加解密效率低下
③.混合加密
通信双方,先使用非对称加密保护对称秘钥协商过程。对称秘钥协商完毕后,使用对称秘钥加密传输。

https加密流程:(将身份验证(CA认证)与加密传输(混合加密)合在一起使用)
1.通信双方生成一对秘钥,使用公钥信息到权威机构生成一个CA证书
2.通信建立连接后,数据传输前,将证书先传输给对方
3.双方收到对方的证书后,进行解析,得到机构信息以及公钥信息
4.对机构信息进行验证
5.身份验证通过后,使用公钥加密数据(随机数+对称加密算法列表),发送给对方
6.双方收到对方使用公钥加密的数据后,使用私钥进行解密
7.给对方也发送一个随机数+对称加密算法列表
8.通过双方的随机数与算法列表生成一个对称秘钥
9.使用这个协商的对称秘钥加密通信

传输层

应用层协议目的是了解指定协议的实现便于我们以后使用
传输层:负责应用程序之间的数据传输–TCP/UDP
了解协议的实现,体会协议的特性,理解对于上层程序编程的影响

UDP协议

UDP协议格式
在这里插入图片描述
16位源端-对端端口:用于描述识别通信两端进程
16位数据报(UDP)长度:能够存储最大数字65535–udp报文总大小最大不能超过64k
16位校验和:采用二进制反码求和算法–校验接收方接收到的数据与发送方发送的数据是否一致。
协议特性
无连接:通信时不需要建立连接,只要知道对方地址就可以直接发送数据
不可靠:不保证数据安全、有序到达对端。
面向数据报:无连接的,不可靠的,无序的,有最大长度限制的传输方式
1.ucp传输时,sendto发送的数据会被发送到发送缓冲区中,而udp协议并不会等待,而是直接对数据封装头部,进行发送
2.udp传输时,收到的数据会被放到接收缓冲区中,而udp保证数据是整条交付,不会出现半条或多条交付。

编程影响
1.不保证安全到达:需要会在应用层使用tcp所使用的一些机制实现
2.不保证有序到达:需要在应用层进行包序管理
3.udp报文有最大长度限制:报文最大长度小于64k,因此发送大块数据的时候,需要在应用层进行数据分包进行发送
4.udp实现的是整条交付:因此接收方revcfrom所给予的buf(定义的缓冲区)足够大,能够一次性取出一条数据。

TCP协议

tcp协议格式:
在这里插入图片描述
16位源端-对端端口:描述识别两端
32位序号-确认号:进行包序管理
4位头部长度:以4字节为单位,表示tcp报头最大有60字节,最小20字节
6位保留
6位标志位
URG:紧急指针是否有效;
ACK:表示响应;
PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走;
RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文段;
SYN:请求建立连接;我们把携带SYN标识的称为同步报文段;
FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段;
16位窗口大小:实现华东窗口机制
16位校验和:校验接收的数据与发送的数据是否一致
16位紧急指针:标识哪部分数据是紧急数据

协议特性:面向连接,可靠传输,面向字节流
面向连接:连接管理+状态管理
连接管理:
三次握手连接建立在这里插入图片描述> 四次挥手断开连接
在这里插入图片描述
问题
1.为什么握手是三次,而挥手是四次?
握手:tcp是一个全双工通信,两端都必须确认对方是否具有数据收发的能力。两次不安全,四次没必要。
挥手:fin包只能表示对方不再发送数据了,不代表对方不再接收数据,因此有可能被动关闭方还会继续发送数据,因此这种情况下就不能直接发送fin包,而是等待上层用户不在发送数据了,调用close或者shutdown才会发送fin包。因此被动关闭方的ack和fin并不是一起发送的。
2.tcp三次握手失败了,两端是如何处理的?
服务端回复ack+syn后,如果超时得不到ack回复,则会发送rst重置连接报文,然后释放新建套接字。
3.TIME_WAIT有什么用?
TIME_WAIT是主动关闭方在断开连接过程中进行最后一次ack回复后进入的状态。如果主动关闭方回复最后一次ack后直接释放资源,就有可能在新的客户端中使用原来的这个地址信息,在上次ack丢失的情况下收到重传的fin对新连接造成影响。TIME_WAIT更多的是为了保护客户端启动不会使用刚关闭的套接字地址信息,进而不会受到上个套接字的通信遗留问题影响。
详细说明:如果被动关闭方没有收到最后一次回复,则会重传fin;假设没有TIME_WAIT,主动关闭方最后一次恢复后直接释放资源。这时候如果客户端重新启动了一个套接字使用的刚好是之前的地址信息,这个套接字就有可能收到重传的这个fin。被动关闭方一致等待最后一个ack,但是这时候如果新的客户端启动发送syn,则与状态对应不上。
TIME_WAIT等待2个MSL时间之后,释放资源,等待两个msl是为了保证能够对重传的fin进行处理,以及保证本次通信的所有数据都消失在网络中不会对新的连接造成影响。
4.一台主机上出现了大量的TIME_WAIT是什么原因?如何解决?
TIME_WAIT是套接字主动关闭连接,最终进入的状态,因此一台主机出现大量TIME_WAIT意味着大量的主动关闭了套接字。
解决方法:
①.减少TIME_WAIT等待时间
②.使用套接字选项:地址复用
int setsockopt(int fd, int level, int optname, void* optval, int optlen);
level:SOL_SOCKET;optname:SO_REUSEADDR – 地址复用
5.一台主机上出现了大量的CLOSE_WAIT是什么原因?如何解决?
close_wait是被动关闭方,在收到fin包进行ack回复之后进入的状态。这个状态是等待上层用户层调用close/shutdown(wr)后发送fin包的一个状态。
如果主机上出现了大量的close_wait的连接,那么意味着可能在代码中没有关闭套接字。

TCP连接保活机制
通信两端在长时间没有数据通信的情况下,服务端会每隔一段时间向客户端发送一个保活探测数据包(要求对方进行回复),若连续多次没有收到回复,则认为连接已经断开。
默认7200s,每隔75s,9次无回复则断开
这些数值可以通过设置套接字选项进行设置。
连接断开对于程序的影响:recv返回0,send会触发SIGPIPE异常

可靠传输:保证数据有序,安全到达对端
1.面向连接
2.协议字段中的序号与确认序号,进行包序管理,实现有序传输。
3.确认应答机制:接收方针对收到的每一条数据进行确认回复
4.超时重传机制:发送数据等待超时时无确认回复后,认为数据丢失进行重传。
5.协议字段的校验和字段:校验数据一致性,不一致则丢弃,发送重传请求
6.避免丢包:
①.发送方发送数据过快,过多,导致接收方接收缓冲区满溢导致丢包
解决方案:滑动窗口机制–进行流量控制
每一方都会有一个:接收窗口,发送窗口
发送窗口:后沿:发送起始序号;前沿:结束发送位置。前沿减后沿不能大于对方的窗口大小
接收窗口:后沿:起始接收序号;前沿:结束接受位置。前沿减后沿不能大于剩余空间大小
停等协议:收到确认回复后才会发送下一条
回退n步协议:从丢失的数据开始进行重新传输
选择重传协议:哪条丢了就重传哪条
②.传输过程中,网络状态突然不好,导致大量丢包重传
解决方案:拥塞机制 – 以慢启动快增长的形式进行传输
实现原理:发送方维护一个拥塞窗口,用于限制当前所能发送的数据大小,而这个拥塞窗口以指数层级增长,实现网络探测,防止传输过程中网络状态突然变差继续大量发送导致的大量丢包。
7.性能的提升:避免无谓的一些性能损失
确认序号:是告诉发送方确认序号之前的所有数据都已经接收成功,避免因为中间的某个确认回复丢失而导致的重传。
快速重传机制:接收方在接收数据时,先接收到了后发的数据,则认为前边的数据有可能丢失了,则连续间隔发送三条前边数据的重传请求(确认序号为丢失的数据起始序号),发送方收到连续三条重传请求,主要目的是为了减少超时等待时间。三条重传请求是为了防止延迟到达的情况。
延迟应答机制:接收方收到数据后,延迟确认回复
接收方接收数据后如果立即进行回复,大概率窗口大小都会变小,延迟应答是为了在延迟期间上层可能将数据取出,尽量保证窗口大小,保证传输吞吐量。
捎带应答机制:将确认回复的信息,放到即将要发送的数据报头中,捎带一块传输给对方,尽可能减少纯报头的确认回复(一个报头至少20字节)

TCP如何实现可靠传输
1.可靠传输:面向连接,包序管理,确认应答,超时重传,校验和
2.避免丢包:滑动窗口,拥塞机制
3.提高性能:延迟应答,捎带应答,延迟发送
UDP如何实现可靠传输
在应用层用过tcp实现可靠传输的机制来实现

面向字节流:基于连接,可靠的,有序的,双向的一种字节流(以字节为单位)
TCP要发送的数据都会被放到发送缓冲区中,通信时tcp会从缓冲去中取出合适大小的数据(不大于mss大小),封装头部进行发送。
好处:传输比较灵活
坏处:会产生粘包问题 – 将多条数据当做一条进行处理-无法分辨数据边界
本质原因:tcp并不维护数据边界
解决方案:则需要程序员在应用层进行数据边界管理–区分数据边界
具体技术:特殊字符,数据定长,应用层头部加上数据长度字段
UDP不存在粘包问题。数据整条交付

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/281799.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【探讨】基于卷积神经网络深度学习模型的光场显微三维粒子空间分布重建

光场显微粒子图像测速技术通过单光场相机即可实现微尺度三维速度场的测量&#xff0c;但单光场相机角度信息有限&#xff0c;导致粒子重建的轴向分辨率低、重建速度慢。基于此&#xff0c;提出一种基于卷积神经网络深度学习模型的光场显微粒子三维空间分布重建方法&#xff0c;…

说说你对webpack的理解?解决了什么问题?

文章目录 一、背景二、问题三、是什么参考文献 一、背景 Webpack 最初的目标是实现前端项目的模块化&#xff0c;旨在更高效地管理和维护项目中的每一个资源 模块化 最早的时候&#xff0c;我们会通过文件划分的形式实现模块化&#xff0c;也就是将每个功能及其相关状态数据各…

浅谈如何自我实现一个消息队列服务器(2)——实现 broker server 服务器

文章目录 一、实现 broker server 服务器1.1 创建一个SpringBoot项目1.2 创建Java类 二、硬盘持久化存储 broker server 里的数据2.1 数据库存储2.1.1 浅谈SQLiteMyBatis 2.1.2 如何使用SQLite 2.2 使用DataBaseManager类封装数据库操作2.3 文件存储消息2.3.1 存储消息时&#…

Visual Studio 2022进行文件差异比较

前言 Visual Studio 2022在版本17.7.4中发布在解决方案资源管理器中比较文件的功能&#xff0c;通过使用此功能&#xff0c;可以轻松地查看两个文件之间的差异&#xff0c;包括添加、删除和修改的代码行。可以逐行查看差异&#xff0c;并根据需要手动调整和编辑文件内容以进行…

100个openharmony开源demo:1.日历

准备用开发者手机写100个开源的demo不知道能不能实现&#xff0c;日拱一卒&#xff0c;期待蜕变。 第一个demo&#xff1a;日历&#xff0c;借鉴了网上的日历算法&#xff0c;自己用arkts写了界面和点击事件&#xff0c;各位可根据此demo写自己的日历选择器等组件。 1.目录结…

【Godot 3.5组件】简单血条组件HealthBar

说明 本文原文写自2022年&#xff0c;内容基于Godot3.5。是本人早期进行Godot组件化和自定义节点探索时的产物&#xff0c;当时的代码和思想可能不太成熟&#xff0c;但贴出来&#xff0c;供需要学习组件化基础思路的同学食用。 概述 血条作为一个非常基础和常见的组件&…

【C++】---string的模拟

【C】---string的模拟 一、string类实现1.string类的构造函数2.swap&#xff08;&#xff09;函数3.拷贝构造函数4.赋值运算符重载5.析构6.迭代器7.operator[ ]8.size9.c_str&#xff08;&#xff09;10.reserve&#xff08;&#xff09;11.resize&#xff08;&#xff09;12.p…

【C语言】linux内核pci_enable_device函数和_PCI_NOP宏

pci_enable_device 一、注释 static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) {struct pci_dev *bridge;int err;int i, bars 0;/** 此时电源状态可能是未知的&#xff0c;可能是由于新启动或者设备移除调用。* 因此获取当前的电源状态&…

【Apache ShenYu源码】如何实现负载均衡模块设计

ShenYu是一个异步的&#xff0c;高性能的&#xff0c;跨语言的&#xff0c;响应式的 API 网关。有关ShenYu的介绍可以戳这。 一、前瞻 今天我们尝试不同的代码阅读方式&#xff0c;按模块来去阅读源码&#xff0c;看看效果如何。 本次阅读锁定在shenyu-loadbalancer&#xf…

WM8978 —— 带扬声器驱动程序的立体声编解码器(4)

接前一篇文章&#xff1a;WM8978 —— 带扬声器驱动程序的立体声编解码器&#xff08;3&#xff09; 九、寄存器概览与详解 1. 整体概览 WM8978芯片共有58个寄存器&#xff0c;整体总表如下&#xff1a; 2. 详细说明 在此&#xff0c;只介绍WM8978较为常用的那些寄存器。 &…

HBCalculator 程序:通过 VMD 可计算分子动力学模拟中氢键密度和强度的一维和二维分布

分享一个通过 VMD 可计算分子动力学模拟中氢键密度和强度的一维和二维分布程序 HBCalculator。 感谢论文的原作者&#xff01; 主要内容 “氢键是分子系统中关键的非共价相互作用&#xff0c;对生物、化学和能量相关过程产生重大影响&#xff1b;因此&#xff0c;描述氢键信息…

Eureka的介绍和作用,以及搭建

一、Eureka的介绍和作用 Eureka是Netflix开源的一种服务发现和注册工具&#xff0c;它为分布式系统中的服务提供了可靠的服务发现和故障转移能力。Eureka是Netflix的微服务架构的关键组件之一&#xff0c;它能够实时地监测和管理服务实例的状态和可用性。 在Eureka架构中&…

智能合约 之 ERC-20介绍

什么是ERC20 ERC20全称为Ethereum Request for Comment 20&#xff0c;是一种智能合约标准&#xff0c;用于以太坊网络上的代币发行 姊妹篇 - 如何部署ERC20 ERC20的应用场景 代币化资产&#xff0c;例如&#xff1a;USDT 是一种以美元为背书的ERC20代币&#xff0c;每个USDT代…

scDEA一键汇总12种单细胞差异分析方法 DESeq2、edgeR、MAST、monocle、scDD、Wilcoxon

问题来源 单细胞可以做差异分析&#xff0c;但是究竟选择哪种差异分析方法最靠谱呢&#xff1f; 解决办法 于是我去检索文献&#xff0c;是否有相关研究呢&#xff1f; https://academic.oup.com/bib/article/23/1/bbab402/6375516 文章指出&#xff0c;现有的差异分析方法…

Java推荐算法——特征加权推荐算法(以申请学校为例)

加权推荐算法 文章目录 加权推荐算法1.推荐算法的简单介绍2.加权推荐算法详细介绍3.代码实现4.总结 1.推荐算法的简单介绍 众所周知&#xff0c;推荐算法有很多种&#xff0c;例如&#xff1a; 1.加权推荐&#xff1a;分为简单的特征加权&#xff0c;以及复杂的混合加权。主要…

23 OpenCV 直方图比较

文章目录 直方图比较的目的相关性计算 (CV_COMP_CORREL)卡方计算 (CV_COMP_CHISQR)十字计算(CV_COMP_INTERSECT)巴氏距离计算 (CV_COMP_BHATTACHARYYA )compareHist 直方图比较算子示例 直方图比较的目的 直方图比较的目的是衡量两幅图像之间的相似度或差异度。通过计算图像的颜…

Vue 3中实现基于角色的权限认证实现思路

一、基于角色的权限认证主要步骤 在Vue 3中实现基于角色的权限认证通常涉及以下几个主要步骤&#xff1a; 定义角色和权限&#xff1a;首先需要在后端服务定义不同的角色和它们对应的权限。权限可以是对特定资源的访问权限&#xff0c;比如读取、写入、修改等。用户认证&#…

C#非强签名dll搜索顺序

由于不是强签名dll&#xff0c;所以无效考虑全局程序集缓存 (GAC)。 预备工作 新建解决方案ClassLibrary1,新建类库ClassLibrary1,新建控制台程序ShowDllLoc。 利用VS添加引用。 一&#xff0c;利用app.config设置codebase&#xff0c;设置dll的加载路径为&#xff1a;code…

前后端分离项目springsecurity实现用户登录认证快速使用

目录 1、引入依赖 2、创建类继承WebSecurityConfigurerAdapter &#xff08;1&#xff09;重写里面的configure(HttpSecurity http)方法 &#xff08;2&#xff09;重写AuthenticationManager authenticationManagerBean() &#xff08;3&#xff09;密码加密工具 3、继承…

市场复盘总结 20240321

仅用于记录当天的市场情况&#xff0c;用于统计交易策略的适用情况&#xff0c;以便程序回测 短线核心&#xff1a;不参与任何级别的调整&#xff0c;采用龙空龙模式 一支股票 10%的时候可以操作&#xff0c; 90%的时间适合空仓等待 二进三&#xff1a; 进级率中 23% 最常用的…