【Linux网络】网络应用层的 http 和 https协议

news2024/11/23 15:01:07

文章目录

    • 1、http协议
      • 1.1 认识URL
      • 1.2 http协议格式
      • 1.3 http的方法(GET和POST)
      • 1.4 状态码
      • 1.5 cookie
      • 1.6 短连接和长连接
    • 2、https协议
      • 2.1 常见的加密方式
      • 2.2 探究https协议的加密
      • 2.3 CA证书

1、http协议

在之前学习序列化和反序列化的时候,认识到主机之间传输结构数据的时候,最好是通过某种约定将结构数据序列化成一串字符串,接收方再通过反序列化将字符串转换成结构数据。以上说的这种约定,其实可以看成是用户层通信的一种协议,是由程序猿自己定的。

实际上,已经有很多大佬写了很多很好的应用层上的协议供我们参考学习。http协议(超文本传输协议)就是其中一个。

1.1 认识URL

早期的网址是用http协议的,不过经过长时间的技术发展后,目前网址一般都是用https协议的。
不过得先认识http,这样才能更好了解https。

下面就是一种网址格式。

在这里插入图片描述

实际上,目前的URL普遍省略了以下部分:
登录信息(一般都用一个可以互动的窗口让用户填写)
端口号(端口号被缺省了,因为每个协议所有的端口号被固定了,比如http:80,https:443

那么URL究竟是个什么呢?
URL(uniform Resource Locator)又被称为统一资源定位符,顾名资源定位符,在互联网上用来标识和定位资源的一种文本字符串。URL可以帮助我们快速定位到网络上的不同资源。(比如网页、图片、视频等)

URL如何做到?
在URL中,http协议指定了如何访问资源,服务器地址(也称域名,域名是可以转换成IP地址的)标识了互联网上主机的唯一性,因此再通过特定端口,就可以访问到特定的服务端进行连接。可以看到URL上还有带层次的文件路径,没错,服务端一般是在Linux系统上搭建的,这就是需要访问的linux服务器的资源文件路径。

值得注意的是,这个文件路径不是简单的在服务器上的绝对路径的,而是大多数情况下,服务端进程(Web服务器)会将请求的URL映射到服务端的文件系统路径。例如,如果基础路径是服务端上的目录/wwwroot,请求的URL是“index.html”,那么请求的资源文件路径就是/wwwroot/index.html。


urlencode和urldecode
可以看到像/ ? : 这样的字符在URL中有特殊的含义,为了不让这些字符随意出现,如果参数中要有一些特殊字符就需要通过urlencode进行转义。
一些网站对于中文,也会进行转义,比如在bing中搜索C++,就变成了C%2B%2B。
在这里插入图片描述
unldecode就是逆过程。

转义的规则如下: 将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式(比如‘+’的ASCII码是43,对应16进制就是2B)

1.2 http协议格式

http在被设计的时候也有着自己的格式。
在这里插入图片描述

任何协议的请求或接受都是报头+有效载荷。

其中请求部分

  1. \r\n就是一个约定分隔符,代表每一行的结束。
  2. 请求报头中有着一些属性(具体的下面说),有效载荷中代表一些用户和服务端的交互数据。(比如登录信息、Up主上传的音频、视频)
  3. 读取完整报头时按行读取直到读取空行,空行的作用就是能代表报头读取完毕,接下来就是有效载荷部分。
  4. 如何保证读完正文呢? 在报头中有一个记录正文长度的属性Content-Length。

其中响应方

  1. http常用版本是http1.0和http1.1,可以看到客户端和服务端都有自己的版本,这也是为了服务端能根据版本信息去适配低版本客户端而有的。
  2. 状态码和状态码描述,可以代表响应的情况。(比如访问网页的404错误码和错误信息)
  3. 响应正文就是客户端需要拿到的资源。


下面通过一个在传输层以TCP协议传输的代码来体会一下。

#include <iostream>
#include <string>
#include <string.h>
#include <fstream>
#include <sys/socket.h>
#include <assert.h>
#include <stdarg.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <pthread.h>

using namespace std;

#define CRLF "\r\n"
#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define HOME_PAGE "index.html"
#define ROOT_PATH "wwwroot"

std::string getPath(std::string http_request)
{
    std::size_t pos = http_request.find(CRLF);
    if(pos == std::string::npos) return "";
    std::string request_line = http_request.substr(0, pos);
    //GET /a/b/c http/1.1
    std::size_t first = request_line.find(SPACE);
    if(pos == std::string::npos) return "";
    std::size_t second = request_line.rfind(SPACE);
    if(pos == std::string::npos) return "";

    std::string path = request_line.substr(first+SPACE_LEN, second - (first+SPACE_LEN));
    //当url为/时,不能代表获得全部资源,而是类似主页的index
    if(path.size() == 1 && path[0] == '/') path += HOME_PAGE;
    return path;
}

std::string readFile(const std::string &recource)
{
    std::ifstream in(recource, std::ifstream::binary);
    if(!in.is_open()) return "404";
    std::string content;
    std::string line;
    while(std::getline(in, line)) content += line;
    in.close();
    return content;
}


//http的请求 {method} 路径 版本
void handlerHttpRequest(int sock)
{
    //读取发送方信息
    char buffer[10240];
    ssize_t s = read(sock, buffer, sizeof buffer);
    if(s > 0) cout << buffer;

    //开始响应

    //获得资源在服务端下的地址
    std::string path = getPath(buffer);
    std::string recource = ROOT_PATH;
    recource += path;
    std::cout << recource << std::endl;

    //读取html资源(前端代码)
    std::string html = readFile(recource);

    //http响应方
    std::string response;
    //报头
    response = "HTTP/1.0 200 OK\r\n";
    response += "Content-Type: text/html\r\n";
    response += ("Content-Length: " + std::to_string(html.size()) + "\r\n");
    response += "Set-Cookie: this is my cookie content;\r\n";
    //空行
    response += "\r\n";
    //回应正文
    response += html;

    //发送给客户端
    send(sock, response.c_str(), response.size(), 0);
}


class tcpServer
{
public:
    tcpServer() :_listenSock(-1), _quit(false)
    {}

    tcpServer(uint16_t port, const std::string& ip = "") 
        :_listenSock(-1)
        ,_serverPort(port)
        ,_serverIp(ip)
        ,_quit(false)
    {}

    ~tcpServer()
    {
        if(_listenSock >= 0)
            close(_listenSock);
    }

    void init()
    {
        //1、创建套接字
        _listenSock = socket(AF_INET, SOCK_STREAM, 0);
        if(_listenSock < 0)
        {
            exit(1);          
        }


        //2、bind服务器信息
        //2.1 填充服务器信息
        struct sockaddr_in server;
        //类似memset 清0
        bzero(&server, sizeof(server));
        //填写协议簇
        server.sin_family = PF_INET;
        //填写端口 因为是向网络中传输,所以要进行网络字节序的转换
        server.sin_port = htons(_serverPort);
        //填写IP 如果ip为空,设置为INADDR_ANY, 系统会帮忙填写
        server.sin_addr.s_addr = _serverIp.empty() ? INADDR_ANY : inet_addr(_serverIp.c_str());

        //2.2 bind 绑定
        if(bind(_listenSock, (const struct sockaddr*)&server, sizeof(server)) < 0)
        {
            exit(2);
        }

        //3、监听 获取连接 因为tcp是需要建立连接的,这一步相当于等待客户端请求连接
        if(listen(_listenSock, 5) < 0)
        {
            exit(3);
        }
    }

    void start()
    {
        while(!_quit)
        {
            //4.建立连接

            //客户端信息
            struct sockaddr_in peer;
            socklen_t peerLen = sizeof(peer);
            //accept返回一个文件描述符
            //_listenSock用来寻找连接
            //serviceSock用来建立连接
            //accept 将一个输出新参数传入,运行完后接收
            int serviceSock = accept(_listenSock, (struct sockaddr*)&peer, &peerLen);
            if(_quit)
            {
                break;
            }
            if(serviceSock < 0)
            {
                exit(4);
            }
            //至此服务器和客户端的连接建立完成

            //5.获取客户端信息
            //获取客户端ip
            std::string peerIp = inet_ntoa(peer.sin_addr);
            uint16_t peerPort = ntohs(peer.sin_port);
            signal(SIGCHLD, SIG_IGN);
            if(fork() == 0)
            {
                close(_listenSock);
                handlerHttpRequest(serviceSock);
                exit(0);
            }

            close(serviceSock);
        }
    }

    void quitServer()
    {
        _quit = true;
    }
private:
    //监听套接字
    int _listenSock;
    //端口
    uint16_t _serverPort;
    //ip
    std::string _serverIp;
    //安全退出
    bool _quit;
};

static void Usage(const std::string& proc)
{
    std::cout << "Usage:\t\n" << proc << " port : ip" << std::endl;
}

int main(int argc, char* argv[])
{
    if(argc != 2 && argc != 3)
    {
        Usage(argv[0]);
        exit(0);
    }

    std::string serviceIp;
    uint16_t servicePort;

    if(argc == 2)
    {
        servicePort = atoi(argv[1]);
    }

    if(argc == 3)
    {
        serviceIp = argv[2];
    }

    tcpServer ts(servicePort, serviceIp);
    ts.init();
    ts.start();
    return 0;
}

前端测试代码
基础路径是服务端前提下:/wwwroot/index.html
在这里插入图片描述

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>测试</title>
</head>

<body>
    <h3>hello my server!</h3>
    <p>我终于测试完了我的代码</p>
    <form action="/a/b/c.html" method="get">
        Username: <input type="text" name="user"><br>
        Password: <input type="password" name="passwd"><br>
        <input type="submit" value="Submit">
    </form>
</body>

</html>

运行代码,通过浏览器输入IP和端口让浏览器以客户端的方式向服务端发送以下信息。

在这里插入图片描述

服务端收到数据以后,向客户端响应,就读取了对应的前端html代码。

在这里插入图片描述

Linux下的telnet命令
telnet命令,能够通过远程的,以协议方式登录某种服务。

当出现^],就说明连接成功,就可以通过ctrl+] 然后回车,输入请求行信息,就可以获取响应端报头和有效载荷内容。

这里是引用

1.3 http的方法(GET和POST)

因为HTTP其它的方法不太常用。
这里只具体说GET和POST。

GET方法

可以注意到,在之前的前端代码中。method就是get。

method="get"

还是上面那个代码,在响应网站中输入账号和密码后,会发现一个这样的现象。
在这里插入图片描述
首先,404错误的出现肯定不是重点,因为我的代码没有提供确认按钮请求之后的响应。重点是这次URL中,账号和密码竟然出现在了参数部分。

是的,http中GET方法提交参数,会以明文的方式将我们对应的参数,拼接在URL中。


POST方法
其它都一样,只将method改为post。

method="post"

在这里插入图片描述
可以看到提交的参数放到了正文中。
在这里插入图片描述

GET和POST的比较

  1. GET通过URL传参,POST通过正文传参。
  2. GET方法传参不私密直接暴露出来,POST正文传参相对比较私密。(但是都不安全,通过抓包非常容易能得到)
  3. GET方法传参一般传小数据,一般一些比较大的内容都通过POST方式传(文件、电影)

1.4 状态码

在这里插入图片描述

这里只关注这几个常见的和常用的
200代表客户端响应成功。
当因为客户端错误时,会有404(Not Found)无法访问,403(Forbidden)禁止访问。
当服务器错误,会有504(bad gateway),错误的网关。


较为重要的是3XX重定向状态码。其中有301永久重定向和302临时重定向。


HTTP常见Header

  • Content-Type: 数据类型(text/html等)
  • Content-Length: Body的长度
  • Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;
  • User-Agent: 声明用户的操作系统和浏览器版本信息;(这个可以用在,比如用户在下载网页的时候,可以通过对不同的OS类型,率先提供匹配的下载版本。)
  • referer: 当前页面是从哪个页面跳转过来的;
  • location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问;
  • Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能;


重定向状态码
对应服务端两者每什么区别,区别是在客户端上的。
301:永久重定向,比如一个拥有很多客户的旧网站需要关闭更换新的网站,那么就可以通过这个永久重定向跳转到新的网站。这就需要客户记住新的网站,不过现在有些浏览器会记录经常访问的网站。
302:临时重定向,比如一些服务要升级,就可以临时重定向到一个新的网站,这个拷贝之前旧的服务,当服务升级完成后,就可以关闭这个临时重定向。这对客户不影响。

直接通过代码演示,将上述代码的处理函数改为以下。

void handlerHttpRequest(int sock)
{
    //读取发送方信息
    char buffer[10240];
    ssize_t s = read(sock, buffer, sizeof buffer);
    if(s > 0) cout << buffer;

    std::string response = "http/1.0 302 Movedtemporatily\r\n";
    //填写location属性
    response += "Location: https://blog.csdn.net/Ahaooooooo\r\n";
    response += "\r\n";
    send(sock, response.c_str(), response.size(), 0);
}

通过浏览器输入ip:端口,结果也是成功返回到我的主页
在这里插入图片描述

1.5 cookie

其实http协议有一个特点是无状态。也就是http没有记录,要什么给什么。

不过我们经常会看到一个现象,就是我们登录网站时,在填写一次登录信息后,不管是关浏览器还是关机。下一次再登录网站时,就默认是登录状态了。这明显不符合http的特点。其实就是cookie策略在帮助记录的。

在这里插入图片描述

还是通过最开始的代码运行。

通过网站访问可以看到,cookie就是浏览器维护的文件,真正存在磁盘或者是一种内存级文件(这也符合那种关闭浏览器就需要重新登录的)
在这里插入图片描述

cookie的安全性问题
上述讨论简单传文件的是在http1.0中较为常见的。如果一些恶意软件将cookie软件找到,那么里面看到的就是裸露的数据,这就会造成安全性问题。(cookie这种机制也不止运用在浏览器,也会在一些软件中。)
因此现在主流的都是一种cookie+session的方案。
在这里插入图片描述

这让信息只放到了服务端,由产品公司进行保护,而公司相对于客户的安全能力肯定是更高的。

1.6 短连接和长连接

http在不同版本有不同的连接方式,在对应属性中有Connection字段,代表着不同连接。
http 1.0: closed 意为连接后响应一次就关闭对应文件描述符。
http 1.1: keep-alive 意为保持长连接,不用总是连接完再断开。

在这里插入图片描述

用户所看到的完整网页内容,背后可能是无数次http请求。http主流底层采用的是TCP协议!如果采用短连接,那么在底层tcp就会不断的进行3次握手和四次挥手(可以理解为连接和断开),这就会出现低效率问题。

长连接,对于多个请求访问,在一次连接时就可以都收到,并且为了防止出现顺序问题,也会通过一种Pipeline技术,使得依次响应。
其实http是无连接的,它只是借助了tcp建立连接的功能。因此http被称为一个超文本传输协议,是一个无状态无连接的应用层协议。

2、https协议

http因为其传输数据都是以明文方式进行传输的,因此在传输的过程中,是极有可能被第三方通过一些手段获取或更改数据,而造成数据安全问题的。
https通过在http的基础上添加了一层软件层:SSL/TLS加密协议,使得数据在传输的时候具有一定安全性。
在这里插入图片描述

http默认端口是80,https默认端口是443。
因此它们两个是两个不同的服务。
那么是不是https可以直接取代http了?
并不是,https因为需要加密解密的存在,肯定会导致效率更低的问题。因此在一些比较安全同时看重效率的场景下,http还是很有用的。

2.1 常见的加密方式

首先一个明文通过一个密钥的转换,就称为了一个密文。

对称加密: 采用单钥密码系统加密的方式,可同时用作信息加密和解密。(比如按位与 a^key = b, b^key = a),它的特点是计算量小,加密效率高

非对称加密: 需要两个密钥来加密和解密。两个密钥分别是公钥和私钥。
用法除了正着用也可以反着用。它的特点是算法越复杂,安全性越高。因此相对于对称加密,加密速度非常慢
在这里插入图片描述

数据摘要(也称数据指纹): 原理是将数据通过一种单向散列函数(Hash函数)生成一串固定的长度的数据摘要。数据摘要不是一种加密算法,而是用来判断数据有没有被篡改。

数字签名: 数据摘要通过加密就得到了数字签名。(这个下面讲)

2.2 探究https协议的加密

因为数据安全问题,数据应该在加密之后以密文的方式在网络中进行传输,那么具体的方案,应该是什么样的呢?

方案一:只使用对称加密
如果

方案二:只使用非对称加密
K代表公钥,K’代表私钥
在这里插入图片描述

方案三:只使用非对称加密
在这里插入图片描述
并且,前面说过非对称加密是非常影响效率的,因此如果考虑效率,这个方案也是绝对不行的。

方案四:非对称加密+对称加密
在这里插入图片描述
第四个方案,其实效率问题已经解决了,但是还是有密钥在传输的过程中被第三方篡改的问题。为了解决这个问题,就需要下面一个方案。

2.3 CA证书

服务器在使用https之前,需要向CA机构申领一份CA数字证书,数字证书里面含有证书申请者信息、公钥信息等。服务端将证书传给浏览器,浏览器从其中拿去公钥。证书像是一个服务端公钥的身份证,证明其权威性。
在这里插入图片描述

申请证书时,需要在特定的平台生成,并且会给一对密钥,也就是公钥和私钥,其中公钥会随着CA证书交给客户端,服务端自己保存私钥。

在这里插入图片描述

当服务端申请CA证书的时候,CA机构会对该服务端进行审核,并且为该网站形成数字签名,具体过程如下:

  1. CA机构有非对称的公钥A和私钥A’
  2. CA机构将证书的明文数据通过Hash函数,形成数据摘要。
  3. 数据摘要通过私钥加密就得到一个签名S,附加到数据上就成了数字证书,就可以颁发给服务端了。

方案五:CA证书+非对称加密+对称加密

在这里插入图片描述

首先在传输CA证书的过程中,中间人是可以获得CA证书的,也可以对其修改,但这是没有用的。
因为在Client收到证书时,需要通过Hash函数将证书明文转换成散列值和通过证书公钥解密的数字签名进行比对,如果不同就说明出了问题,就能察觉的到。
中间人也无法伪造证书,因为其中涉及了服务端的信息。

总结:超文本传输http协议解决了客户端访问服务端资源的问题,https则完善了其安全问题。因此在应用层上,认识这两个协议非常有必要。

本章完~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 之 vi 文本编辑器(二)

1、文本编辑器简介 Linux 中最常用的文本编辑器&#xff1a; vi&#xff1a;类 Unix 系统中默认的文本编辑器 vim&#xff1a;vi 编辑器的增强版本&#xff0c;习惯上也称 vi vi 文本编辑器的作用和特性&#xff1a; vi 可以执行插入、删除、查找、替换等众多文本操作&…

网络计算模式复习(四)

MapReduce MapReduce分布式处理技术、分布式的文件系统GFS、结构化的BigTable存储系统是Google的三个核心技术。 Map-Reduce&#xff1a;用于大规模数据集的并行计算。 &#xff08;分而治之&#xff09;将要执行的问题拆解成Map&#xff08;映射&#xff09;和Reduce&#x…

SpringBoot整合FreeMarker

一、FreeMarker简述 在线文档&#xff1a;http://freemarker.foofun.cn/ FreeMarker 也是一款模板引擎技术&#xff0c;它是一种基于模板和要改变的数据&#xff0c;并用来生成输出文本(HTML网页&#xff0c;电子邮件&#xff0c;配置文件&#xff0c;源代码等)的通用工具。当然…

创建一个react项目

文章目录 1&#xff1a;命令行输入2&#xff1a;在vs的终端中输入npm start 来启动项目3&#xff1a;删除src目录中的干扰项4&#xff1a;去掉index.js中的严格模式节点JSX介绍JSX中使用js表达式原生js调用三元运算符列表渲染条件渲染三元表达式逻辑&&运算 分支逻辑类名…

Setting up SSH Host ...问题解决

一、问题可能原因&#xff1a; 网速问题导致下载过慢&#xff0c;超时 二、解决方式&#xff1a;手动下载安装 1、确定VSCode commit id&#xff0c;如下图所示 2、拼接请求&#xff0c;下载vscode server包 Arm&#xff1a;https://update.code.visualstudio.com/commit:换…

【AUTOSAR】【通信安全】CRC

目录 一、概述 二、功能说明 2.1 通用行为 2.2 8位CRC计算 2.2.1 8位SAE J1850 CRC计算 2.2.2 8位0x2F多项式CRC计算 2.3 16位CRC计算 2.3.1 16位CCITT-FALSE CRC16 2.3.2 16位0x8005多项式CRC计算 2.4 32位CRC计算 2.4.1 32位以太网CRC计算 2.4.2 32位0xF4ACFB13多…

AIGC产业研究报告 2023——图像生成篇

易观&#xff1a;今年以来&#xff0c;随着人工智能技术不断实现突破迭代&#xff0c;生成式AI的话题多次成为热门&#xff0c;而人工智能内容生成&#xff08;AIGC&#xff09;的产业发展、市场反应与相应监管要求也受到了广泛关注。为了更好地探寻其在各行业落地应用的可行性…

jvm之常用命令行工具

写在前面 本文已起看下给我们的Java程序看病常用到的工具都有哪些&#xff0c;通过工具得到指标&#xff0c;通过指标分析病情&#xff0c;从而给出对应的治疗方案。 1&#xff1a;jps/jinfo 用来获取运行的jvm进程信息&#xff0c;一般我们使用该命令来获取进程号&#xff…

CTF权威指南 笔记 -第二章二进制文件- 2.4 -动态链接

目录 静态文件的缺点 动态链接 位置无关代码 延迟绑定 _dl_runtime_reslove 函数定义 深入审视 静态文件的缺点 随着可执行文件的增加 静态链接带来的浪费空间问题就会愈发严重 如果大部分可执行文件都需要glibc 那么在链接的时候就需要把 libc.a链接进去 如果一个libc…

Spark大数据处理讲课笔记3.6 RDD容错机制

文章目录 零、本讲学习目标一、RDD容错机制&#xff08;一&#xff09;血统方式&#xff08;二&#xff09;设置检查点方式 二、RDD检查点&#xff08;一&#xff09;RDD检查点机制&#xff08;二&#xff09;与RDD持久化的区别&#xff08;三&#xff09;RDD检查点案例演示 三…

Matlab 多项式拟合

一、线性 1、多项式 corrcoef函数 corrcoef函数用来计算矩阵相关系数。 (1)、corrcoef(x)&#xff1a;若x为一个矩阵&#xff0c;返回的则是一个相关系数矩阵。 (2)、corrcoef(x,y)&#xff1a;计算列向量x、y的相关系数&#xff0c;要求x、y具有相等的元素个数。如果x、y是矩…

2023河南土著双非硕士——毕业季秋招春招就业经验分享(仅限于在河南找工作,毕业想留河南)

作为一名河南土生土长的人&#xff0c;本硕皆就读于河南某双非一本&#xff0c;是一个实打实的河南土著&#xff0c;河南作为互联网就业的贫困环境&#xff0c;相较于CSDN博客上那么多动不动就腾讯、阿里、字节等大厂的就业经验分享&#xff0c;我更想分享一下我在河南省内找工…

百度文心一言正式亮相,数说故事受邀成为首批内测企业

3月16日下午&#xff0c;百度在北京召开新闻发布会&#xff0c;正式推出基于百度新一代大语言模型的生成式AI产品——文心一言&#xff0c;百度创始人、董事长兼首席执行官李彦宏现场展示了文心一言在文学创作、商业文案创作、数理推算、中文理解、多模态生成五个使用场景中的综…

卖期权的时候,我们在卖什么?

一直在思考一个问题&#xff0c;卖期权到底是怎么回事&#xff1f;卖实值期权、平值期权、虚值期权背后的本质有什么区别&#xff1f;卖近期的和远期的期权背后的本质又是什么?我们用沪深300指数期权来研究一下。 我们先从数据上来直观感受一下。上面这个表格是2020-12-09日这…

基于R语言的贝叶斯时空数据模型实践技术

时间&#xff0d;空间数据&#xff08;以下简称“时空数据”&#xff09;是最重要的观测数据形式之一&#xff0c;很多科学研究的数据都以时空数据的形式得以呈现&#xff0c;而科学研究目的可以归结为挖掘时空数据中的规律。另一方面&#xff0c;贝叶斯统计学作为与传统统计学…

【OpenCV】 2D-2D:对极几何算法原理

2D-2D匹配: 对极几何 SLAM十四讲笔记1 1.1 对极几何數學模型 考虑从两张图像上观测到了同一个3D点&#xff0c;如图所示**。**我们希望可以求解相机两个时刻的运动 R , t R,t R,t。 假设我们要求取两帧图像 I 1 , I 2 I_1,I_2 I1​,I2​之间的运动,设第一帧到第二帧的运动为…

MiniGPT-4部署过程

文章目录 项目背景部署过程环境配置与文件准备部署推理报错1报错2 项目背景 2023年4月19日&#xff0c;开源项目MiniGPT-4发布&#xff0c;该项目是由KAUST&#xff08;沙特阿卜杜拉国王科技大学&#xff09;&#xff0c;是几位博士开发的。 项目地址&#xff1a;https://gith…

Spark大数据处理讲课笔记3.4 理解RDD依赖

文章目录 零、本讲学习目标一、RDD依赖二、窄依赖&#xff08;一&#xff09;map()与filter()算子&#xff08;二&#xff09;union()算子&#xff08;三&#xff09;join()算子 三、宽依赖&#xff08;一&#xff09;groupBy()算子&#xff08;二&#xff09;join()算子&#…

字符设备驱动

字符设备就是按字节流进行读写的设备&#xff0c;读写数据分先后顺序&#xff0c;如点灯&#xff0c;IIC&#xff0c;SPI&#xff0c;LCD等都是字符设备&#xff0c;这些设备的驱动就叫字符设备驱动。 include/linux/fs.h中 file_operations 结构体为内核驱动操作函数集合&…

如何关闭tomcat?tomcat端口号被占用怎么办

我tomcat一跑就报被占用怎么办&#xff1f;我没开tomcat呀&#xff01;&#xff01; 这种情况一般是你上一次打开tomcat没有关tomcat服务就关闭了变成软件&#xff08;如强行关闭正在运行tomcat的idea&#xff09;&#xff0c;这样你在开tomcat就会显示端口号占用了&#xff0…