網絡編程(4)

【0】復習

sockfd=socket();
//指定網絡信息
bind();
listen();
//創建表 fd_set rfds,tempfds;
FD_ZERO();
FD_SET(sockfd);
max =sockfd
while(1)
{
    tempfds=rfds;
    select(max+1,&tempfds)
    if(FD_ISSET(scokfd,&tempfds))
    {    acceptfd=accept();
        FD_SET(acceptfd,&rfds);
        if(max<acceptfd)max=acceptfd;
    }
    for(int i=sockfd+1;i<=max;i++)
    {    if(FD_ISSET(i,&tempfds))
        {    ret=recv(i);
            if(ret==0)
            {close(i);    FD_CLR(i,&rfds);
                while(!FD_ISSET(max,&rfds))max--;        
            }
            printf();
        }
    }
}

【1】組播(多播)

理論

單播方式只能發給一個接收方。

廣播方式發給所有的主機。過多的廣播會大量占用網絡帶寬,造成廣播風暴,影響正常的通信。

播是一個人發送,加入到多播組的人接收數據。

多播方式既可以發給多個主機,又能避免像廣播那樣帶來過多的負載(每臺主機要到傳輸層才能判斷廣播包是否要處理)

多播地址

D類:224.0.0.1-239.255.255.254

接收者

  1. 創建套接字(socket)
  2. 置多播屬性,將自己的IP加入到多播組中

  1. 指定網絡信息
  2. 綁定套接字(bind)
  3. 接收消息(recvfrom)
  4. 關閉套接字(close)
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>int main(int argc, char const *argv[])
{char buf[128] = {0};int ret = 0;int acceptfd;// 1.創建數據包套接字int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){perror("socket err");return -1;}printf("sockfd:%d\n", sockfd);// 設置多播屬性struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(argv[2]); // 組播IP
    mreq.imr_interface.s_addr = INADDR_ANY;         // 自己IPsetsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,sizeof(mreq));// 指定網絡信息struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1])); // 端口// saddr.sin_addr.s_addr = inet_addr("192.168.50.79"); // IP//  saddr.sin_addr.s_addr = inet_addr("0.0.0.0"); // IP
    saddr.sin_addr.s_addr = INADDR_ANY; // IPint len = sizeof(caddr);// 綁定:綁定服務器信息(IP地址\端口號等)if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0){perror("bind err");return -1;}printf("bind okk\n");while (1){// read(acceptfd,buf,sizeof(buf));
        ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&caddr, &len);if (ret < 0){perror("recv err");return -1;}elseprintf("ip:%s port:%d says:%s\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port), buf);memset(buf, 0, sizeof(buf));}close(sockfd);return 0;
}

發送者

  1. 創建套接字(socket)
  2. 指定網絡(服務器)信息
  3. 發送消息(sendto)
  4. 關閉套接字(close)

【2】數據庫:SQLite

SQLITE的存儲結構:B樹

1. 數據庫安裝

測試數據庫是否安裝

sqlite3 -version

2. 數據庫安裝命令

將壓縮包拿到虛擬機路徑下

tar xf sqlite-autoconf-3460000.tar.gz

cd sqlite-autoconf-3460000

./configure

make

sudo make install

3.? 圖形化工具的安裝

sudo apt-get install sqlitebrowser

2. 數據庫的概念

數據庫是“按照數據結構來組織、存儲和管理數據的倉庫”。是一個長期存儲在計算機內的、有組織的、可共享的、統一管理的大量數據的集合。

數據庫是存放數據的倉庫。它的存儲空間很大,可以存放百萬條、千萬條、上億條數據。但是數據庫并不是隨意地將數據進行存放,是有一定的規則的,否則查詢的效率會很低。當今世界是一個充滿著數據的互聯網世界,充斥著大量的數據。即這個互聯網世界就是數據世界。數據的來源有很多,比如出行記錄、消費記錄、瀏覽的網頁、發送的消息等等。

3. 常用的數據庫

大型數據庫 :Oracle

中型數據庫 :Server是微軟開發的數據庫產品,主要支持windows平臺

小型數據庫 : MySQL是一個小型關系型數據庫管理系統。開放源碼 (嵌入式不需要存儲太多數據)

MySQLSQLite區別:

MySQL和SQLite是兩種不同的數據庫管理系統,它們在多個方面有所不同。

1. 性能和規模:MySQL通常用于大型應用程序和網站,它可以處理大量數據和高并發訪問。SQLite則更適合于小型應用程序或移動設備,因為它是一個輕量級的數據庫引擎,不需要獨立的服務器進程,可以直接訪問本地文件。

2. 部署和配置:MySQL需要單獨的服務器進程來運行,需要配置和管理數據庫服務器。而SQLite是一個嵌入式數據庫,可以直接嵌入到應用程序中,不需要單獨的服務器進程。

3. 功能和特性:MySQL提供了更多的功能和高級特性,比如存儲過程、觸發器、復制和集群支持等。SQLite則是一個輕量級的數據庫引擎,功能相對較少,但對于簡單的數據存儲和檢索已經足夠。

4. 跨平臺支持:SQLite在各種操作系統上都能夠運行,而MySQL需要在特定的操作系統上安裝和配置數據庫服務器。

總之,MySQL適用于大型應用程序和網站,需要處理大量數據和高并發訪問,而SQLite適用于小型應用程序或移動設備,對性能和規模要求沒有那么高。

4. SQLite基礎

SQLite的源代碼是C,其源代碼完全開放。它是一個輕量級的嵌入式數據庫。

SQLite有以下特性:

零配置一無需安裝和管理配置;

儲存在單一磁盤文件中的一個完整的數據庫;

數據庫文件可以在不同字節順序的機器間自由共享;

支持數據庫大小至2TB(1024G = 1TB);//嵌入式足夠

足夠小,全部源碼大致3萬行c代碼,250KB;

比目前流行的大多數數據庫對數據的操作要快;

操作方式:

手動:

使用sqlite3工具,手工輸入命令

命令行輸入

代碼:

利用代碼編程,調用接口

5. 基本語句的基本使用

【騰訊文檔】SQL基礎語句基本使用

SQL基礎語句基本使用

sqlile3編程

官方文檔:List Of SQLite Functions

中本版:SQLite Insert 語句 - SQLite 中文版 - UDN開源文檔

頭文件:#include <sqlite3.h>

編譯:gcc sqlite.c -lsqlite3

6. 函數接口

打開數據庫
?

int sqlite3_open(char *path, sqlite3 **db);

功能:打開sqlite數據庫,如果數據庫不存在則創建它

參數:path: 數據庫文件路徑

db: 指向sqlite句柄的指針

返回值:成功返回SQLITE_OK(0),失敗返回錯誤碼(非零值)

返回錯誤信息

char *sqlite3_errmsg(sqlite3 *db);

功能: 獲取錯誤信息

返回值:返回錯誤信息

使用: fprintf(stderr,"sqlite3_open failed %s\n",sqlite3_errmsg(db));

關閉數據庫

int sqlite3_close(sqlite3 *db);

功能:關閉sqlite數據庫

返回值:成功返回SQLITE_OK,失敗返回錯誤碼

執行sql語句接口

int sqlite3_exec(

sqlite3 *db, /* An open database */

const char *sql, /* SQL to be evaluated */

int (*callback)(void*,int,char**,char**), /* Callback function */

void *arg, /* 1st argument to callback */

char **errmsg /* Error msg written here */

);

功能:執行SQL操作

參數:db:數據庫句柄

sql:要執行SQL語句

callback:回調函數(滿足一次條件,調用一次函數,用于查詢)

再調用查詢sql語句的時候使用回調函數打印查詢到的數據

arg:傳遞給回調函數的參數

errmsg:錯誤信息指針的地址

返回值:成功返回SQLITE_OK,失敗返回錯誤碼

回調函數:

typedef int (*sqlite3_callback)(void *para, int f_num,

char **f_value, char **f_name);

功能:select:每找到一條記錄自動執行一次回調函數

參數:para:傳遞給回調函數的參數(由 sqlite3_exec() 的第四個參數傳遞而來)

f_num:記錄中包含的字段數目

f_value:包含每個字段值的指針數組(列值)

f_name:包含每個字段名稱的指針數組(列名)

返回值:成功返回SQLITE_OK,失敗返回-1,每次回調必須返回0后才能繼續下次回調

不使用回調函數執行SQL語句(只用于查詢)
int sqlite3_get_table(sqlite3 *db, const  char  *sql, char ***resultp,  int *nrow,  int *ncolumn, char **errmsg);功能:執行SQL操作
參數:db:數據庫句柄
    sql:SQL語句
    resultp:用來指向sql執行結果的指針
    nrow:滿足條件的記錄的數目(但是不包含字段名(表頭 id name score))
    ncolumn:每條記錄包含的字段數目
    errmsg:錯誤信息指針的地址
返回值:成功返回SQLITE_OK,失敗返回錯誤碼

#include <sqlite3.h>
#include <stdio.h>int callback(void *buf, int num, char **value, char **name);int main(int argc, char const *argv[])
{sqlite3 *db;// 打開或創建數據庫if (sqlite3_open("stu.db", &db) != SQLITE_OK){fprintf(stderr, "open err:%s\n", sqlite3_errmsg(db));return -1;}printf("open okk\n");// 創建表char *errmsg = NULL;if (sqlite3_exec(db, "create table if not exists stu (id int ,name string,score float)", NULL, NULL, &errmsg) != SQLITE_OK){fprintf(stderr, "create err:%s\n", sqlite3_errmsg(db));fprintf(stderr, "create err:%s\n", errmsg);return -1;}printf("create okk\n");// 插入數據/*if(sqlite3_exec(db,"insert into stu values(1,'lihua',0)",NULL,NULL,&errmsg)!=SQLITE_OK){fprintf(stderr, "insert err:%s\n", errmsg);return -1;}printf("insert okk\n");*/int num = 0;printf("請輸入要輸入的學生人數:");scanf("%d", &num);char sql[64] = {0};int id;char name[32] = {0};float score;for (int i = 0; i < num; i++){printf("請輸入學生信息:");scanf("%d %s %f", &id, name, &score);sprintf(sql, "insert into stu values(%d,'%s',%f)", id, name, score);if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){fprintf(stderr, "insert err:%s\n", errmsg);return -1;}printf("insert okk\n");}// 查找數據if (sqlite3_exec(db, "select * from stu where id=10", callback, "hello", &errmsg) != SQLITE_OK){fprintf(stderr, "select err:%s\n", errmsg);return -1;}printf("select okk\n");// 專門用于查詢的函數// char **result = NULL;// int row, column;// sqlite3_get_table(db, "select * from stu where id=10", &result, &row, &column, &errmsg);// printf("row:%d column:%d\n", row, column);// int k=0;// printf("aaaa:%s ", result[k++]);// for (int i = 0; i <= row; i++)// {//     for (int j = 0; j < column; j++)//         printf("%s ", result[k++]);//     putchar(10);// }// 關閉數據庫sqlite3_close(db);return 0;
}// 每查詢到一條符合條件的數據,就調用一次此函數
int callback(void *buf, int num, char **value, char **name)
{static int a = 1;printf("******************** \n");printf("%d :%s \n", a++, (char *)buf);// num:列數// name:列名// value:查詢到的值for (int i = 0; i < num; i++)printf("%s ", name[i]);putchar(10);for (int i = 0; i < num; i++)printf("%s ", value[i]);putchar(10);return 0; // 必須返回0,不然報錯
}

練習:數據庫基本語句的使用,并完成下面練習題

sqlite3 stu2.db
CREATE TABLE stu2 (
    學號 VARCHAR(10) PRIMARY KEY,
    姓名 VARCHAR(50),
    年齡 INT,
    性別 VARCHAR(10),
    家庭住址 VARCHAR(100),
    聯系電話 VARCHAR(20)
);
ALTER TABLE stu2 ADD 學歷 VARCHAR(50);
ALTER TABLE stu2 DROP COLUMN 家庭住址;
INSERT INTO stu2 (學號, 姓名, 年齡, 性別, 聯系電話, 學歷)
VALUES ('1', 'A', 22, '男', '123456', '小學'), 
('2', 'B', 20, '女', '114567', '初中'),
('3', 'C', 25, '男', '345678', '高中')
('4', 'D', 22, '男', '345678', '大專');UPDATE stu2
SET 學歷 = '大專'
WHERE 聯系電話 LIKE '11%';DELETE FROM stu2
WHERE 姓名 LIKE 'C%' AND 性別 = '男';SELECT 姓名, 學號
FROM stu2
WHERE 年齡 < 22 AND 學歷 = '大專';SELECT 姓名, 性別, 年齡
FROM stu2
ORDER BY 年齡 DESC;

  1. 完成FTP項目

模擬FTP核心原理:客戶端連接服務器后,向服務器發送一個文件。文件名可以通過參數指定,服務器端接收客戶端傳來的文件(文件名隨意),如果文件不存在自動創建文件,如果文件存在,那么清空文件然后寫入。

項目功能介紹:

均有服務器和客戶端代碼,基于TCP寫的。

在同一路徑下,將客戶端可執行代碼復制到其他的路徑下,接下來在不同的路徑下運行服務器和客戶端。

相當于另外一臺電腦在訪問服務器。

客戶端和服務器鏈接成功后出現以下提示:三個功能

***********put filename**********//從客戶端所在路徑上傳文件

***********get filename**********//從服務器所在路徑下載文件

**************quit***************//退出(可只退出客戶端,服務器等待下一個客戶端鏈接)

可拓展功能:客戶端可以獲取服務器路徑下有哪些文件

list:客戶端請求文件列表 → 服務器遍歷目錄 → 發送文件名 → 發送 "end" 結束。

putfile:客戶端發送 "put filename" → 服務器創建文件 → 接收數據寫入文件 → 收到 "end" 結束。

getfile:客戶端發送 "get filename" → 服務器讀取文件 → 發送數據 → 發送 "end" 結束。

服務器

#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>void putfile(int, char *);
void getfile(int acceptfd, char *p);int main(int argc, char const *argv[])
{
    char buf[128] = {0};
    int ret;
    int acceptfd;
    // 1.創建套接字(socket())------------------------》有手機
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {        perror("socket err");
        return -1;
    }
    printf("sockfd:%d\n", sockfd); // 3
    // 2.指定網絡信息--------------------------------------》有號碼
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1])); // 網絡字節序端口號
    // saddr.sin_addr.s_addr = inet_addr("192.168.51.78"); // 虛擬機IP
    // saddr.sin_addr.s_addr = inet_addr("0.0.0.0"); // 虛擬機IP
    saddr.sin_addr.s_addr = INADDR_ANY; // 虛擬機IP
    int len = sizeof(caddr);
    // 3.綁定套接字(bind())----------------------------》綁定手機(插卡)
    if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("bind err");
        return -1;
    }    printf("bind okk\n");
    // 4.監聽套接字(listen())--------------------------》待機
    // 將主動套接字變為被動套接字
    // 隊列1(未完成連接隊列):4 5 6
    // 隊列2(已完成連接隊列):3
    if (listen(sockfd, 6) < 0)
    {
        perror("listen err");
        return -1;
    }
    printf("listen okk\n");
    while (1)
    {
        // 5.阻塞等待接收客戶端連接請求(accept())-------------》接電話
        acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
        // accept會返回一個用于通信的文件描述符
        // 在tcp服務器中,有兩類套接字,一類是socket函數返回(1個),用于鏈接的文件描述符
        // 一類是accept函數返回的(1個或者多個),用于通信的文件描述符
        if (acceptfd < 0)
        {
            perror("acceptfd err");
            return -1;
        }
        printf("acceptfd:%d\n", acceptfd);
        printf("ip:%s    port: %d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
        // 6.接受發送消息(send()/recv())-------------》通話
        while (1)
        {
            ret = recv(acceptfd, buf, sizeof(buf), 0); //==>read
            if (ret < 0)
            {
                perror("recv err");
                return -1;
            }
            else if (ret == 0)
            {
                printf("client exit\n");
                break;
            }
            printf("buf:%s\n", buf);            if (!strncmp(buf, "put ", 4))
                putfile(acceptfd, buf);
            if (!strncmp(buf, "get ", 4))
                getfile(acceptfd, buf);
            memset(buf, 0, sizeof(buf));
        }        // 7.關閉套接字(close)---------------------------》掛斷電話
        close(acceptfd);
    }
    close(sockfd);
    return 0;
}void putfile(int acceptfd, char *p)
{
    int ret = 0;
    int fd = open(p + 4, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    if (fd < 0)
    {
        perror("open err");
        return;
    }
    char buf[128] = {0};
    while (1)
    {
        ret = recv(acceptfd, buf, sizeof(buf), 0);
        if (ret < 0)
        {
            perror("recv err");
            return;
        }
        if (!strcmp(buf, "end"))
            break;
        write(fd, buf, strlen(buf));
        memset(buf, 0, sizeof(buf));
    }
}void getfile(int acceptfd, char *p)
{
    char buf[128] = {0};
    int ret = 0;
    int fd = open(p + 4, O_RDONLY);
    if (fd < 0)
    {
        perror("open err");
        return;
    }
    while (1)
    {
        ret = read(fd, buf, sizeof(buf) - 1);
        buf[ret] = '\0';
        if (ret == 0)
            break;
        send(acceptfd, buf, sizeof(buf), 0);
    }
    send(acceptfd, "end", sizeof(buf), 0);
    close(fd);
    return;
}

客戶端

#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>void show();
void list(int sockfd);
void putfile(int, char *);
void getfile(int sockfd, char *p);int main(int argc, char const *argv[])
{
    char buf[128] = {0};
    int ret;
    // 1.創建套接字(socket())-
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {        perror("socket err");
        return -1;
    }
    printf("sockfd:%d\n", sockfd); // 3
    // 2.指定網絡信息
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    // saddr.sin_port = htons(5678);                       // 網絡字節序端口號
    // saddr.sin_addr.s_addr = inet_addr("192.168.51.78"); // 虛擬機IP
    saddr.sin_port = htons(atoi(argv[2]));      // 網絡字節序端口號
    saddr.sin_addr.s_addr = inet_addr(argv[1]); // 虛擬機IP
    // 3.請求連接
    if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("connect err");
        return -1;
    }
    printf("connect okk\n");
    // 4.接受發送消息(send()/recv())-------------》通話
    while (1)
    {
        show();
        fgets(buf, sizeof(buf), stdin);
        // HELLO
        // printf("buf:%s\n", buf);
        if (buf[strlen(buf) - 1] == '\n')
            buf[strlen(buf) - 1] = '\0';
        if (!strcmp(buf, "quit"))
            break;
        send(sockfd, buf, sizeof(buf), 0);        if (!strncmp(buf, "put ", 4))
            putfile(sockfd, buf);
        if (!strncmp(buf, "get ", 4))
            getfile(sockfd, buf);
    }    // 7.關閉套接字(close)---------------------------》掛斷電話
    close(sockfd);
    return 0;
}void show()
{
    printf("------------put filename------------\n");
    printf("------------get filename------------\n");
    printf("----------------quit----------------\n");
}void putfile(int sockfd, char *p)
{
    char buf[128] = {0};
    int ret = 0;
    int fd = open(p + 4, O_RDONLY);
    if (fd < 0)
    {
        perror("open err");
        return;
    }
    while (1)
    {
        ret = read(fd, buf, sizeof(buf) - 1);
        buf[ret] = '\0';
        if (ret == 0)
            break;
        send(sockfd, buf, sizeof(buf), 0);
    }
    send(sockfd, "end", sizeof(buf), 0);
    close(fd);
    return;
}void getfile(int sockfd, char *p)
{
    int ret = 0;
    int fd = open(p + 4, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    if (fd < 0)
    {
        perror("open err");
        return;
    }
    char buf[128] = {0};
    while (1)
    {
        ret = recv(sockfd, buf, sizeof(buf), 0);
        if (ret < 0)
        {
            perror("recv err");
            return;
        }
        if (!strcmp(buf, "end"))
            break;
        write(fd, buf, strlen(buf));
        memset(buf, 0, sizeof(buf));
    }
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97369.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97369.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97369.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Windows系統提示“找不到文件‘javaw‘”

1. Java 未安裝或安裝不完整javaw.exe 是 Java 運行環境&#xff08;JRE&#xff09;的核心文件&#xff0c;用于運行 Java 程序&#xff08;如.jar 文件&#xff09;。如果你的電腦沒有安裝 Java&#xff0c;或安裝過程中 javaw.exe 被誤刪&#xff0c;系統就會找不到它。2. J…

【PCIE系列】1---PCIE系統拓撲結構分析

架構由點對點鏈路&#xff08;Links&#xff09;組成&#xff0c;用于互連組成系統的一系列組件。下圖展示了一個示例拓撲結構。該圖描述了一個有層次的體系架構實例&#xff0c;其包含根復合體&#xff08;Root Complex, RC&#xff09;、多個端點&#xff08;I/O設備&#xf…

SpringBoot防止重復提交(2)

例如&#xff1a;多次點擊提現按鈕問題描述&#xff1a;在提現操作中&#xff0c;用戶可能會多次點擊提現按鈕&#xff0c;導致多個相同的請求發送到服務器&#xff0c;從而引發重復提現的問題。為了解決這一問題&#xff0c;必須保證每個提現請求只能執行一次&#xff0c;防止…

mysql zip包安裝步驟

下載地址 windows MSI Install 安裝包程序。 這里下載zip包&#xff0c;執行安裝過程 確認my.ini 配置的路徑&#xff0c;創建mysql數據服務的data目錄管理員身份cmd 進入bin目錄&#xff0c;開始初始化服務 mysqld --initialize-insecure --usermysql mysqld -install#啟動…

Python 的 argparse 模塊中,add_argument 方法的 nargs 參數

在 Python 的 argparse 模塊中&#xff0c;add_argument 方法的 nargs 參數用于指定命令行參數可以接受的參數數量。你提到的 nargs* 和 nargs 是兩種常見設置&#xff0c;它們分別表示不同的參數數量要求。以下是兩者的詳細區別和含義&#xff1a;1. nargs*: 接受零個或多個參…

嵌入式Linux LED驅動開發

嵌入式Linux LED驅動開發 一、LED驅動概述 本筆記基于IMX6ULL處理器的LED驅動開發&#xff0c;詳細介紹了字符設備驅動開發的基本流程。該驅動實現了對LED的基本控制功能&#xff0c;通過字符設備接口供用戶空間程序調用。 二、LED驅動核心概念 1. 寄存器地址定義 本驅動涉…

Excel Word Pdf 格式轉換

引入aspose包手動更新本地mvn倉庫mvn install:install-file -DfileC:\aspose-cells-22.9.jar -DgroupIdaspose -DartifactIdaspose-cells -Dversion22.9 -Dpackagingjar mvn install:install-file -DfileC:\aspose-pdf-22.9.jar -DgroupIdaspose -DartifactIdaspose-pdf -Dvers…

變頻器實習DAY40 調整測試零伺服PI LDO

目錄變頻器實習DAY40一、工作內容1.1 調整測試零伺服PI二、學習內容2.1 LDOLDO的核心工作原理——“采樣-比較-調整”閉環控制LDO的關鍵參數——選型核心依據LDO與其他穩壓器的選型對比附學習參考網址歡迎大家有問題評論交流 (* ^ ω ^)變頻器實習DAY40 一、工作內容 1.1 調整…

【半導體制造流程概述】

半導體制造流程概述 半導體制造是一個高度復雜且精密的過程&#xff0c;涉及多個關鍵步驟&#xff0c;通常分為以下幾個主要階段&#xff1a;設計、晶圓制備、光刻、刻蝕、摻雜、薄膜沉積、互連和封裝測試。 文章目錄半導體制造流程概述晶圓制備光刻刻蝕摻雜薄膜沉積互連封裝測…

為什么大模型需要文檔預處理:從數據到智能的關鍵一步

在人工智能&#xff0c;尤其是大語言模型&#xff08;LLM, Large Language Models&#xff09;的應用落地過程中&#xff0c;數據質量與處理流程的重要性正逐漸被各行各業所認識。無論是企業內部構建知識庫、自動化文檔審核&#xff0c;還是面向用戶提供智能問答服務&#xff0…

50.【.NET8 實戰--孢子記賬--從單體到微服務--轉向微服務】--新增功能--二期功能規劃

啰嗦了這么多文章&#xff0c;我們終于進入到了二期功能的開發。這篇文章我們先來規劃一下二期要做的功能&#xff0c;在一期功能中&#xff0c;我們完成了基礎的記賬功能&#xff0c;但是作為一個記賬軟件&#xff0c;僅有這些功能是遠遠不夠的。我們需要更多的功能來滿足用戶…

Oracle下載安裝(學習版)

1. 下載&#xff08;學習版&#xff09; 網址&#xff1a;軟件下載 | Oracle 中國 2. 安裝 解壓縮 雙擊可執行文件 下一步 選同意&#xff0c;下一步 下一步 設置密碼&#xff08;自己記住&#xff09; 開始安裝 測試安裝是否成功

`basic_filebuf`、`basic_ifstream`、`basic_ofstream`和 `basic_fstream`。

C 文件 I/O 模板類深度解析 文章目錄C 文件 I/O 模板類深度解析1. basic_filebuf 深度解析1.1 類模板定義詳解1.2 關鍵成員變量1.3 核心成員函數實現原理1.3.1 open() 函數實現1.3.2 overflow() 函數實現1.4 完整示例&#xff1a;自定義緩沖策略2. basic_ifstream 深度解析2.1 …

計算機畢設 java 阿歹果園養雞場管理系統 基于 SSM 框架的果園養雞場全流程管理系統設計與實現 Java+MySQL 的養殖生產與進銷存一體化平臺開發

計算機畢設 java 阿歹果園養雞場管理系統ky7dc9 &#xff08;配套有源碼 程序 mysql數據庫 論文&#xff09;本套源碼可以先看具體功能演示視頻領取&#xff0c;文末有聯xi 可分享 隨著農業養殖規模化發展&#xff0c;傳統果園養雞場依賴人工記錄、紙質臺賬的管理模式&#xf…

生成式BI工具(WrenAI)

生成式 BI 工具支持自然語言查詢數據庫&#xff0c;自動生成 SQL 與可視化圖表&#xff0c;被金融分析師和數據科學家廣泛采用。 WrenAI是由Canner團隊開發的開源生成式BI&#xff08;GenBI&#xff09;智能體&#xff0c;致力于通過自然語言交互實現數據庫查詢、可視化生成和洞…

論文Review 3DGS PGSR | TVCG2024 ZJU-3DV | 幾何約束的3DGS表面重建

基本信息 題目&#xff1a;PGSR: Planar-based Gaussian Splatting for Efficient and High-Fidelity Surface Reconstruction 來源&#xff1a;TVCG2024 學校&#xff1a;ZJU-3DV 是否開源&#xff1a;https://github.com/zju3dv/PGSR 摘要&#xff1a;3DGS表面重建 最近…

最新After Effects2025下載安裝(含安裝包)AE 2025 保姆級下載一鍵安裝圖文教程

文章目錄一、After Effects 2025下載二、After Effects 2025安裝教程三、核心功能升級詳解四、系統配置與兼容性說明一、After Effects 2025下載 ①夸克網盤下載鏈接&#xff1a;https://pan.quark.cn/s/a06e6200e64c 二、After Effects 2025安裝教程 1.解壓安裝包:找到下載…

【網絡安全領域】邊界安全是什么?目前的發展及應用場景

在網絡安全領域&#xff0c;邊界安全&#xff08;Perimeter Security&#xff09; 是指圍繞企業或組織網絡的 “物理與邏輯邊界” 構建的防護體系&#xff0c;核心目標是阻止未授權訪問從外部網絡&#xff08;如互聯網、合作方網絡&#xff09;侵入內部可信網絡&#xff0c;同時…

虛擬機快照對內存與磁盤空間的影響

核心概念&#xff1a;快照是什么&#xff1f;虛擬機快照捕獲的是在某個特定時間點上虛擬機的完整狀態。這包括&#xff1a;磁盤狀態&#xff1a;虛擬磁盤的數據。內存狀態&#xff1a;當時虛擬機內存中的所有內容&#xff08;如果選擇&#xff09;。配置狀態&#xff1a;虛擬機…

免費開源的 Gemini 2.5 Flash 圖片生成器

免費開源的 Gemini 2.5 Flash 圖片生成器&#xff1a;gemini-nano-banana 項目詳解 在 AI 圖片生成領域&#xff0c;大多數工具要么收費昂貴&#xff0c;要么需要復雜的配置。今天為大家介紹一個完全免費開源的解決方案——gemini-nano-banana&#xff0c;一個基于 Google Gemi…