https下载图片

news2024/11/15 9:14:22

OpenSSL用法示例

OpenSSL源码安装

对于ubuntu,懒得编译源码可以直接安装

sudo apt-get install libssl–dev

  /usr/include/openssl/ssl.h

CMakeLists中添加  

link_libraries(ssl crypto)

apt-get安装不需要再制定libssl.a, libcrypto.a的路径了, 就像用libc标准库一样。源码安装要指定-L/path/to/libssl.a或者-L/path/to/libssl.so , -lssl。客户端不需要生成证书。

sale.txt

GET /uploadfile/photo/20231022/37cac8bc693780b740b4e659846689cd.jpg HTTP/1.1
Accept: image/jpeg,image/avif,image/webp,image/apng,*/*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,ja;q=0.6
Connection: keep-alive
Host: img.sx2737.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36

* main.c

#include <string.h>
/* ... */
#include "https.h"


static int get_host_ip(char ip[], char hostname[]) {
    struct ipv4head ipv4List;
    struct ipv4_entry *n1;
    int count = 0;
    /* get ip by Gateway 10.0.0.1 */
    bcl_dns_query(&ipv4List, hostname, "10.0.0.1");
    while(!TAILQ_EMPTY(&ipv4List)) {
        n1 = TAILQ_FIRST(&ipv4List);
        TAILQ_REMOVE(&ipv4List, n1, entries);
        printf("ip=%s\n", n1->data);
        strncpy(ip, n1->data, 16);
        free(n1);
        count += 1;
    }
    return count;
}

int main(int argc, char *argv[]) {
    char path_dst[256];
    char path_src[256];
    char hostname[32] = {'\0'};
    char ip[16] = {'\0'};
    int sockfd = -1;

    bclerrinit();

    strcpy(path_src, "/mnt/e/CLionProjects/arp/fap30/input/sale.txt");
    strcpy(path_dst, "/mnt/e/CLionProjects/arp/fap30/print/sale.jpg");

    strcpy(hostname, "img.sx2737.com");  /* octipus.net, www.google.co.il */
    get_host_ip(ip, hostname);

    printf("path_dst=%s\n", path_dst);
    if (E_FAIL == https_get_body(ip,path_src, path_dst)) {
        bclerrlog(E_SOCKFD_RECV, _FL_, "https_get_body(%s,%s,%s)",ip,path_src,path_dst);
        return E_FAIL;
    }
    bclerrend();
    return E_OK;
}

网关直接固定写的10.0.0.1, 需要改。或者再实现一个拿到网关Gateway IP地址的函数 查DNS

DNS没做缓存,简化版测试查询DNS发UDP包。 一个域名对应多个ip,也不知道多少个ip,用的/usr/include/x86_64-linux-gnu/sys/queue.h  参照下面的bcl_udp.h

#include <sys/queue.h>

* https.h

#ifndef ARP_TEST_HTTPS_H
#define ARP_TEST_HTTPS_H

#include <openssl/ssl.h> /* SSL_Library_init() */
#include <openssl/err.h>

int https_get_body(char *ip, char *in_path, char *out_path);

#endif //ARP_TEST_HTTPS_H

* https.c

/*
 * @ref: https://aticleworld.com/ssl-server-client-using-openssl-in-c/
 * sudo apt-get install libssl–dev
 * -L/path/to/ssl_dir -lssl -lcrypto
 */
#include <string.h> /* memset */
/* ... */
#include "https.h"

extern unsigned int ip2int(const char *ip);

static SSL_CTX *InitCTX(void) {
    SSL_METHOD *method;
    SSL_CTX *ctx;
    OpenSSL_add_all_algorithms();  /* Load cryptos, et.al. */
    SSL_load_error_strings();   /* Bring in and register error messages */
    method = TLSv1_2_client_method();  /* Create new client-method instance */
    ctx = SSL_CTX_new(method);   /* Create new context */
    if ( ctx == NULL ) {
        ERR_print_errors_fp(stderr);
        abort();
    }
    return ctx;
}

ssize_t send_from_file_ssl(SSL *ssl, char *path) {
    byte_t *buf = NULL;
    size_t isz = 0;
    ssize_t outBytes;

    buf = file_get_contents(path, &isz);
    outBytes = SSL_write(ssl, buf, isz);
    /* bcl_xxd(buf, isz); */
    free(buf);
    return outBytes;
}

int https_get_body(char *ip, char *in_path, char *out_path) {
    SSL_CTX *ctx = NULL;
    SSL *ssl;
    int bytes;
#define HTTPS_BUFF_SIZE 4096
    char buf[HTTPS_BUFF_SIZE];
    int sockfd = -1;
    FILE *out = NULL;

    SSL_library_init();
    ctx = InitCTX();
    ssl = SSL_new(ctx);      /* create new SSL connection state */
    sockfd = bcl_tcp_connector(ip2int(ip), 443);
    SSL_set_fd(ssl, sockfd);    /* attach the socket descriptor */
    if ( SSL_connect(ssl) < 0 ) {  /* perform the connection */
        ERR_print_errors_fp(stderr);
        return E_FAIL;
    }
    send_from_file_ssl(ssl, in_path);
    bytes = SSL_read(ssl, buf, HTTPS_BUFF_SIZE);
    /* Dump HTTP header */
    bcl_xxd(buf, bytes);

    out = fopen(out_path, "w");
    if (NULL == out) {
        bclerreg(E_OSCALL, _FL_, "fopen(%s)", out_path);
        return E_FAIL;
    }
    while (0<(bytes = SSL_read(ssl, buf, HTTPS_BUFF_SIZE))) {
        fwrite(buf, 1, bytes, out);
        memset(buf, 0, bytes);
    }
    fclose(out);
    bcl_closesock(sockfd);

    SSL_free(ssl);
    SSL_CTX_free(ctx);
    return E_OK;
}

先准备ssl需要的库, SSL_Libary_init(), 创建SSL_CTX *ctx对象   

封装socket fd为SSL *, 操作SSL *取代 int fd。SSL_read替换recv, SSL_write替换send

close(fd)关闭socket fd。用完SSL_free(ssl),  释放https链接。销毁SSL_CTX *ctx对象 

SSL_read第0次调用拿到http header,再调用得到的是http body。不需要手动解析http \r\n 0x0d 0x0a, 也省了很多麻烦。

int bcl_tcp_connector(u_int32_t _addr, u_int16_t _port) {
    struct sockaddr_in saddr;
    int sock;
    int ret;

    for (;;) {
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock <0) {
            /* ... */
            return E_FAIL;
        }
        memset(&saddr, 0x00, sizeof (saddr));
        saddr.sin_family = AF_INET;
        saddr.sin_addr.s_addr = _addr;
        saddr.sin_port = htons(_port);

        ret = connect(sock, (struct sockaddr *)&saddr, sizeof(saddr));
        if (ret >= 0) {
            return sock;
        }
        /* ERROR connect */
        if (errno == EINTR) {
            bcl_closesock(sock);
            continue;
        }
        char ip[16];
        bcl_int2ip(ip, _addr);
        bclerreg(E_OSCALL, _FL_, "Error connect %s:%d", ip, _port);
        return E_FAIL;
    }
}

创建socket fd,调用connect,常规方法。 

bcl_xxd函数hexdump调试用

uint8_t arc_xxd(byte *s, uint8_t len, void *param);

void bcl_xxd(const void *s, size_t len)
{
    uint16_t line = 0;
    byte *t = (byte *)s;
    uint8_t b;
    size_t left = len;

    for (; ;) {
        if (left > 16) {
            b = arc_xxd(t, 16, &line);
        } else {
            b = arc_xxd(t, left, &line);
        }
        if (b < 1) {break;}
        left -= b;
        if (left <= 0) {break;}
        t += b;
    }
}

uint8_t arc_xxd(byte *s, uint8_t len, void *param)
{
    uint8_t i;
    uint16_t *line = (uint16_t *)param;
    fprintf(stdout, "%08x:", *line << 4);
    for (i = 0; i+2 < len; i+=2) {
        fprintf(stdout, " %02x%02x", s[i], s[i+1]);
    }
    if (i <len) {fprintf(stdout, " %02x", s[i]); i+= 1;}
    if (i <len) {fprintf(stdout, "%02x", s[i]); i+=1;}
    if (i < 16 && 0x00 != (i & 0x01)) { fputs("  ", stdout); i+=1;}
    for (; i <16; i+= 2) {
        fputs("     ", stdout); /* space * 5 */
    }
    fputs("  ", stdout);
    for (i = 0; i <len; i++) {
        if (s[i] <0x20 || s[i] > 0x7e) {
            fputc('.', stdout);
        } else {
            fputc(s[i], stdout);
        }
    }
    fputs("\r\n", stdout);
    *line += 1;
    return i;
}

* bcl_udp.h

#ifndef ERRLOG_BCL_UDP_H
#define ERRLOG_BCL_UDP_H

#include <sys/queue.h>

typedef union {
    unsigned char c[4];
    unsigned int addr;
} IPv4_t;

void IPv4_toString(char *s, IPv4_t ipv4);
/* in_addr_t */ unsigned int ip2int(const char *ip);


struct ipv4_entry {
    char data[16];
    TAILQ_ENTRY(ipv4_entry) entries;
};
TAILQ_HEAD(ipv4head, ipv4_entry);

int bcl_dns_query(struct ipv4head *head, char *host_name, const char *dns_ip);

#endif //ERRLOG_BCL_UDP_H

* bcl_udp.c

#ifdef __cplusplus
extern "C" {
#endif

#include <strings.h> /* bzero */
#include <arpa/inet.h> /* inet_addr */
#include <unistd.h> /* close */
#include <string.h> /* strcat, memset */
#include <stdlib.h> /* getenv(), rand() */

#include "bcl_udp.h"
#include "arclog.h"
#include "bcl_socket.h"

#define PRIVATE static

unsigned int /* in_addr_t */ip2int(const char *ip) {
    IPv4_t un;
    int i, j;
    un.c[0] = un.c[1] = un.c[2] = un.c[3] = 0;
    for (i = 0, j = 0; i < 16 && ip[i] != '\0'; i++) {
        if (0x30 <= ip[i] && ip[i] < 0x3a) { /* '0','9' */
            un.c[j] *= 10;
            un.c[j] += ip[i] - 0x30;
        } else if (ip[i] == 0x2e) { /* '.' */
            j += 1;
        }
    }
    return un.addr;
}


typedef struct {
    u_short transId; /* 0xb6f6 */
    u_short flags;  /* 0x0100 Standard query */
    u_short questions; /* 0x0001 */
    u_char rss[6];  /* 00 00 00 00 00 00 */
} DnsHdr_t;

#define HOST_LEN 64

typedef struct {
    u_char name[2]; /* ptr */
    u_short type; /* 0x0005 alias */
    u_short in; /* 0x0001 */
    u_int32_t ttl; /* 81, 1min21s */
    u_short dataLen;  /* 0x0017, 23 */
    char cname[HOST_LEN];  /* 3www31633com8163jiasu3com */
} __attribute__((packed)) DnsAnswer_t;

/**
 * @ref: https://www.linuxquestions.org/questions/linux-networking-3/dns-packet-structure-289886/
 * @param name "p3-sign.douyinpic.com"
 * @param entry  "7p3-sign9douyinpic3com"
 * @return
 */
PRIVATE char *dns_entry(char *entry, const char *name) {
    const char *p = name;
    char *q = entry;
    int8_t len;

    while ('\0' != *p) {
        len = 0;
        for (; *p && *p != '.'; p++) {
            len += 1;
        }
        *q++ = len;
        memcpy(q, p - len, len);
        q += len;
        p++;
    }
    return q;
}

#define SWAP(a, b, type) do { type _t = a; a = b; b = _t;} while(0);

#define REVERSE(a, b, type)  do { \
   type *p = a, *q = b;           \
   type t;                        \
   if (p > q) { SWAP(p, q, type *);}  \
   for (; p < q; p++, q--) { \
       t = *p; \
       *p = *q; \
       *q = t; \
   } \
} while (0);

void IPv4_toString(char *s, IPv4_t ipv4) {
    int i;
    char *t;
#ifdef __ORDER_LITTLE_ENDIAN__
    for (i = 0; i < 4; i++) {
#else
    for (i = 3; 0 <= i; i--) {
#endif
        t = s;
        while (ipv4.c[i]) {
            *s++ = ipv4.c[i] % 10 + 0x30;
            ipv4.c[i] /= 10;
        }
        REVERSE(s-1, t, char);
        *s++ = '.';
    }
    *(s-1) = '\0';
}

int bcl_dns_query(struct ipv4head *head, char *host_name, const char *dns_ip) {
    int sockfd;
    char buf[1024] = {'\0'};
    struct sockaddr_in dest_addr;
    DnsHdr_t header;
    char *p = NULL;
    off_t queryLen;
    DnsAnswer_t ans;
    IPv4_t ipv4;
    struct ipv4_entry *n1 = NULL;

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        bclerreg(E_OSCALL, _FL_, "socket() UDP");
        return E_FAIL;
    }
    /* DNS address */
    memset(&dest_addr, 0, sizeof(struct sockaddr_in));
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_addr.s_addr = ip2int(dns_ip);
    dest_addr.sin_port = htons(53);  /* DNS port 53 */
    if (connect(sockfd, (const struct sockaddr *) &dest_addr, sizeof(dest_addr)) < 0) {
        bclerreg(E_OSCALL, _FL_, "connect()");
        return E_FAIL;
    }
    /* DNS query packet */
    header.transId = (u_short) rand();
    header.flags = htons(0x0100);
    header.questions = htons(0x0001);
    memset(header.rss, 0, sizeof(header.rss));

    memcpy(buf, &header, sizeof(header));
    p = buf + sizeof(header);
    /* queries: p3-sign.douyinpic.com  */
    p = dns_entry(p, host_name);
    *p++ = '\0';
    /* type A, class IN */
    *p++ = 0x00; *p++ = 0x01;
    *p++ = 0x00; *p++ = 0x01;

    queryLen = p - buf;
    if (send(sockfd, buf, queryLen, 0) < 0) {
        bclerreg(E_OSCALL, _FL_, "send()");
        return E_FAIL;
    }
    memset(buf, 0, 1024);
    if (recv(sockfd, buf, 1024, 0) < 1) {
        bclerreg(E_OSCALL, _FL_, "recv()");
        return E_FAIL;
    }
    p = buf + queryLen;
    /* Answers: buf + queryLen */
    TAILQ_INIT(head);
    while (*p != 0x00) {
        /* bcl_xxd(p, 0xa0); */
        if (*(u_char *)p == 0xc0) {
            /* c0 0c, c0 14 */
            ans.dataLen = ntohs(((DnsAnswer_t *)p)->dataLen);
        }
#if DEBUG
        printf("dataLen=%d\n", ans.dataLen);
        bcl_xxd(((DnsAnswer_t *)p)->cname, ans.dataLen);
#endif
        if (4 == ans.dataLen) { /* IPv4 */
            memcpy(&ipv4, &((DnsAnswer_t *)p)->cname, 4);
            n1 = (struct ipv4_entry *)malloc(sizeof(struct ipv4_entry));
            IPv4_toString(n1->data, ipv4);
            TAILQ_INSERT_TAIL(head, n1, entries);
        }
        p += sizeof(DnsAnswer_t) - HOST_LEN + ans.dataLen;
    }
    return E_OK;
}

#ifdef __cplusplus
};
#endif

查询DNS以上

C:\Windows\system32\wsl.exe --distribution Ubuntu --exec /bin/bash -c "export ESWTDIR=/mnt/e/CLionProjects/arp && export FAPWORKDIR=/mnt/e/CLionProjects/arp/fap30 && cd /mnt/e/CLionProjects/arp/fap30 && /mnt/e/CLionProjects/arp/cmake-build-debug/arp_test ./input/banner.txt banner_3.jpg"
ip=61.164.142.245
ip=115.231.71.216
path_dst=/mnt/e/CLionProjects/arp/fap30/print/sale.jpg
00000000: 4854 5450 2f31 2e31 2032 3030 204f 4b0d  HTTP/1.1 200 OK.
00000010: 0a4c 6173 742d 4d6f 6469 6669 6564 3a20  .Last-Modified:
00000020: 5375 6e2c 2032 3220 4f63 7420 3230 3233  Sun, 22 Oct 2023
00000030: 2030 383a 3036 3a30 3320 474d 540d 0a45   08:06:03 GMT..E
00000040: 7461 673a 2022 3336 3333 3661 6665 3533  tag: "36336afe53
00000050: 3039 6561 3933 6163 6633 3930 6162 3934  09ea93acf390ab94
00000060: 3637 6132 6634 220d 0a43 6f6e 7465 6e74  67a2f4"..Content
00000070: 2d54 7970 653a 2069 6d61 6765 2f6a 7065  -Type: image/jpe
00000080: 670d 0a44 6174 653a 2053 756e 2c20 3232  g..Date: Sun, 22
00000090: 204f 6374 2032 3032 3320 3038 3a30 363a   Oct 2023 08:06:
000000a0: 3034 2047 4d54 0d0a 5365 7276 6572 3a20  04 GMT..Server:
000000b0: 7465 6e63 656e 742d 636f 730d 0a78 2d63  tencent-cos..x-c
000000c0: 6f73 2d68 6173 682d 6372 6336 3465 636d  os-hash-crc64ecm
000000d0: 613a 2031 3534 3631 3131 3537 3934 3831  a: 1546111579481
000000e0: 3535 3537 3339 340d 0a78 2d63 6f73 2d72  5557394..x-cos-r
000000f0: 6571 7565 7374 2d69 643a 204e 6a55 7a4e  equest-id: NjUzN
00000100: 4751 335a 574e 664e 5755 7a4e 6a51 774d  GQ3ZWNfNWUzNjQwM
00000110: 474a 664d 5745 305a 4446 664f 5459 314f  GJfMWE0ZDFfOTY1O
00000120: 4442 6b4e 673d 3d0d 0a43 6f6e 7465 6e74  DBkNg==..Content
00000130: 2d4c 656e 6774 683a 2032 3237 3938 0d0a  -Length: 22798..
00000140: 4163 6365 7074 2d52 616e 6765 733a 2062  Accept-Ranges: b
00000150: 7974 6573 0d0a 582d 4e57 532d 4c4f 472d  ytes..X-NWS-LOG-
00000160: 5555 4944 3a20 3735 3537 3138 3835 3632  UUID: 7557188562
00000170: 3130 3431 3837 3231 320d 0a43 6f6e 6e65  104187212..Conne
00000180: 6374 696f 6e3a 206b 6565 702d 616c 6976  ction: keep-aliv
00000190: 650d 0a58 2d43 6163 6865 2d4c 6f6f 6b75  e..X-Cache-Looku
000001a0: 703a 2043 6163 6865 2048 6974 0d0a 0d0a  p: Cache Hit....

Process finished with exit code 0

查看下载 E:\CLionProjects\arp\fap30\print\sale.jpg

对于http响应body,有的返回是gzip压缩,要用zlib库解压。分段的内容要解析

/** @ref: https://www.iteye.com/blog/dbscx-830644 */
char *http_chunked_parse(char *s, u_int16_t *len) {
    int i;
    /* 0x1000 == 4096 */
    *len = 0;
    for (i = 0; i < 4; i++) {
        if (s[i] == 0x0d && s[i+1] == 0x0a) {
            break;
        }
        /* 32 63 31 0d 0a <=> "3c1\r\n"(LEN=0x2c1, Dec:705) */
        *len *= 16;
        if (0x30<=s[i] && s[i] < 0x40) {
            *len += s[i] - 0x30;
        } else if (0x61 <= s[i] && s[i] < 0x67) {
            *len += s[i] - 0x61 + 10;
        }
    }
    if (s[i] == 0x0d && s[i+1] == 0x0a) {
        s = &s[i] + 2;
    }
    return s;
}

0d 0a 30 0d 0a 0d 0a 结束

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

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

相关文章

柏拉图式爱情是同性之爱,绘画是理念世界的二次模仿

公元前427年&#xff0c;柏拉图出生在雅典。 柏拉图20岁成为苏格拉底的弟子。 有一次&#xff0c;柏拉图问苏格拉底&#xff1a;“什么是爱情&#xff1f;”苏格拉底说&#xff1a;“请穿越麦田&#xff0c;摘一株最大最金黄的麦穗回来。不走回头路&#xff0c;只能摘一次。”…

永恒之蓝漏洞 ms17_010 详解

文章目录 永恒之蓝 ms 17_0101.漏洞介绍1.1 影响版本1.2 漏洞原理 2.信息收集2.1 主机扫描2.2 端口扫描 3. 漏洞探测4. 漏洞利用5.后渗透阶段5.1创建新的管理员账户5.2开启远程桌面5.3蓝屏攻击 永恒之蓝 ms 17_010 1.漏洞介绍 永恒之蓝&#xff08;ms17-010&#xff09;爆发于…

Power BI 傻瓜入门 9. 设计和部署数据模型

本章内容包含&#xff1a; 详细说明设计数据模型的技术要求Power BI Desktop中基本数据模型的设计将数据模型从Power BI Desktop发布到Power BI Services 在数据进入Power BI后对其进行操作既是一门艺术&#xff0c;也是一门科学。导入到任何应用程序中的数据不仅需要注意数据…

7-3、S曲线生成器【51单片机控制步进电机-TB6600系列】

摘要&#xff1a;本节介绍步进电机S曲线生成器的计算以及使用 一.计算原理 根据上一节内容&#xff0c;已经计算了一条任意S曲线的函数。在步进电机S曲线加减速的控制中&#xff0c;需要的S曲线如图1所示&#xff0c;横轴为时间&#xff0c;纵轴为角速度&#xff0c;其中w0为起…

PyCharm 安装 cx_Oracle 失败

我在PyCharm的终端用 pip安装cx_Oracle失败&#xff0c;报错情况如下&#xff1a; ERROR: Could not build wheels for cx_Oracle, which is required to install pyproject.toml-based projects 出错原因&#xff1a; python 的版本太高了&#xff0c;我的是3.11版本的&…

开源思维导图白板工具

https://okso.app https://drawio.com https://tldraw.com https://excalidraw.com

Qt QPixmap绘制一层透明度蒙版

效果 为了在一个图片上绘制透明蒙层效果&#xff0c;思路&#xff1a; 绘制原图。原图上绘制一层透明度。 代码 QImage image(":/resource/icon24_File_Word.png");QPixmap pixmap QPixmap::fromImage(image);ui->label->setPixmap(pixmap);// 重新构造一个…

[Docker]二.Docker 镜像,仓库,容器介绍以及详解

一.Docker 镜像,容器,仓库的简单介绍 通俗来讲:镜像相当于VM虚拟机中的ios文件,容器相当于虚拟机系统,仓库相当于系统中的进程或者执行文件,容器是通过镜像创建的 1.镜像 Docker 镜像就是一个 Linux 的文件系统&#xff08; Root FileSystem &#xff09;&#xff0c;这个文…

np.linspace精确度

前言 今天发现一个大坑&#xff0c;如果是序列是小数的话&#xff0c;不要用np.linspace&#xff0c;而要用np.arrange指定等差序列。比如入下图中a和b是一样的意思&#xff0c;但是b是有较大误差的。 anp.arange(0,4,0.4) bnp.linspace(0,4,10) print("a",a) prin…

HDRP中ShaderGraph自发光(Emission)不工作

在Unity中使用HDRP管线时&#xff0c;在ShaderGraph中制作自发光效果可能会遇到这么一个问题&#xff0c;直接将颜色连到主节点的Emission上没效果。 原因&#xff1a;HDRP场景的灯光是基于物理的&#xff0c;所以灯光的强度远远大于默认的自发光强度&#xff0c;自发光就会不…

蓝桥杯动态规划每日一题

一、买卖股票的最佳时机III 股票最佳时机 1.状态表示 dp[i]:到达i天&#xff0c;所能获得的最大利润 但是我们唯一不清楚的是&#xff0c;他完成了几笔交易&#xff0c;所以不如&#xff0c;就设置一种二维数组 dp[m][3] 2是说第0天是第0笔&#xff0c;第一天是第1笔&#xff…

003 后台系统-搭建前端环境

课程链接 一.下载和配置vscode与nodejs 1.vscode视频链接 2.打开vscode下载以下插件&#xff1a; 3.安装nodejs16.19.0 4.检测nodejs是否安装成功&#xff0c;安装地址无中文 在cmd界面输入命令&#xff1a;node -v 显示版本则安装成功 5.在vscode中创建工作区 在电脑中创…

嵌入式 Tomcat 调校

SpringBoot 嵌入了 Web 容器如 Tomcat/Jetty/Undertow&#xff0c;——这是怎么做到的&#xff1f;我们以 Tomcat 为例子&#xff0c;尝试调用嵌入式 Tomcat。 调用嵌入式 Tomcat&#xff0c;如果按照默认去启动&#xff0c;一个 main 函数就可以了。 简单的例子 下面是启动…

T113-S3-buildroot文件系统tar解压缩gz文件

目录 前言 一、现象描述 二、解决方案 三、tar解压缩.gz文件 总结 前言 本文主要介绍全志T113-S3平台官方SDK&#xff0c;buildroot文件系统tar不支持.gz文件解压缩的问题以及如何配置buildroot文件系统解决该问题的方法介绍。 一、现象描述 在buildroot文件系统中&#xff…

图像压缩(4)《数字图像处理》第八章 8.3节 数字图像水印

图像压缩&#xff08;3&#xff09;《数字图像处理》第八章8.3节数字图像水印 一. 前言二.章节引言三.简单综述三.本章小结四.参考文献四. 小结 一. 前言 始于那本深蓝色的大块头&#xff0c;冈萨勒斯的《数字图像处理》&#xff0c;从此走上了图像信号处理的不归路&#xff0…

Java开发-WebSocket

WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工通信-浏览器和服务器只需要完成一次握手&#xff0c;两者之间就可以创建持久性的连接&#xff0c;并实现 双向数据传输。 使用 导入maven坐标 <dependency><groupId>org.springframework.bo…

【Linux】安装配置虚拟机及虚拟机操作系统的安装

目录 一、操作系统 1. 介绍 2. 功能 3. 有哪些 4. 个人版本和服务器版本的区别 二、VMWare虚拟机 1. 安装 2. 配置 三、安装配置Windows Server 1. 配置 2. 安装 四、虚拟机的环境配置及连接 1. 主机连接虚拟机 2. 虚拟机环境配置及共享 3. 环境配置 一、操作系…

音乐网站播放器前后端【源码好优多】

介绍 音乐网站播放器音乐网站管理系统音乐网站后台 软件架构 使用vuespringbootmybatis-plusmysql技术的前后端分离项目 前端 安装教程 npm install&#xff08;安装运行环境&#xff09; npm run dev&#xff08;运行&#xff09; 需要有node.js环境&#xff0c;不建议使…

设计模式——UML类图

目录 UML类图介绍UML图UML图的分类 关系依赖关系泛化关系实现关系关联关系聚合关系 UML类图 介绍 uml(统一建模语言)&#xff0c;是一种用于软件系统分析和设计的语言工具&#xff0c;他用于帮助软件开发人员进行思考和记录思路的结果UML本身是一套符号的规定&#xff0c;就像…