Linux網絡編程——socket 通信基礎

Linux網絡編程——socket 通信基礎

    • 1. socket 介紹
    • 2. 字節序
      • 2.1 簡介
      • 2.2 字節序舉例
      • 2.3 字節序轉換函數
    • 3. socket 地址
      • 3.1 通用 socket 地址
      • 3.2 專用 socket 地址
    • 4. IP地址轉換(字符串ip -> 整數,主機、網絡字節序的轉換 )
    • 5. TCP 通信流程
    • 6. 套接字函數

1. socket 介紹

????所謂 socket套接字),就是對網絡中不同主機上的應用進程之間進行 雙向通信的 端點的抽象。一個套接字就是網絡上進程通信的一端,提供了 應用層進程 利用網絡協議交換數據的機制。從所處的地位來講,套接字 上聯 應用進程下聯 網絡協議棧,是 應用程序 通過 網絡協議 進行通信的接口,是 應用程序 與 網絡協議根 進行交互的接口。

????socket 可以看成是兩個網絡應用程序進行通信時,各自通信連接中的端點,這是一個 邏輯上的概念。它是網絡環境中 進程間通信API,也是可以被命名尋址通信端點,使用中的每一個套接字都有其類型和一個與之相連進程。通信時其中一個網絡應用程序將要傳輸的一段信息寫入它所在主機的 socket 中,該 socket 通過與 網絡接口卡NIC)相連的傳輸介質將這段信息送到另外一臺主機socket 中,使對方能夠接收到這段信息。socket 是由 IP 地址端口 結合的,提供向應用層進程傳送數據包的機制

????socket 本身有“ 插座 ”的意思,在 Linux 環境下,用于表示 進程間網絡通信特殊文件類型本質為 內核 借助 緩沖區 形成的 偽文件。既然是文件,那么理所當然的,我們可以使用 文件描述符 引用套接字。與管道類似的,Linux 系統將其封裝成文件的目的是為了 統一接口,使得 讀寫套接字讀寫文件 的操作一致。區別是 管道 主要應用于 本地進程間通信,而 套接字 多應用于 網絡進程間數據的傳遞

在這里插入圖片描述

使用 文件描述符 fd 引用 socket
在這里插入圖片描述

套接字通信 分兩部分:

  • 服務器端被動 接受連接,一般不會主動發起連接
  • 客戶端主動 向服務器發起連接

socket 是一套 通信的接口LinuxWindows 都有,但是有一些細微的差別

2. 字節序

2.1 簡介

????現代 CPU 的累加器 一次都能 裝載(至少)4 字節(這里考慮 32 位機),即一個整數。那么這 4 字節 在 內存 中排列的順序 將影響它被累加器裝載成的整數的值,這就是字節序問題。在各種計算機體系結構中,對于字節等的存儲機制有所不同,因而引發了計算機通信領域中一個很重要的問題,即通信雙方交流的信息單元比特字節雙字 等等)應該以什么樣的順序進行傳送。如果不達成一致的規則,通信雙方將無法進行正確的編碼/譯碼從而導致通信失敗。

????字節序,顧名思義 字節的順序,就是大于一個字節類型的數據在內存中的存放順序 (一個字節的數據當然就無需談順序的問題了)。

????字節序 分為 小端字節序Big-Endian) 和 大端字節序Little-Endian)。

  • 小端字節序則 是指 整數的 低位字節 則存儲在內存的 地址 處,而 高位字節 存儲在內存的 地址 處。
  • 大端字節序 是指一個 整數的 最高位字節23 ~ 31 bit)存儲在內存的 地址 處,低位字節0 ~ 7 bit)存儲在 內存的 地址 處;

2.2 字節序舉例

小端字節序

  • 0x 01 02 03 04 (十六進制,四字節ff = 255)

  • 內存的方向 ----->

  • 內存的低位 -----> 內存的高位
    04 03 02 01

0x 11 22 33 44 12 34 56 78八個字節
在這里插入圖片描述

大端字節序

  • 0x 01 02 03 04
  • 內存的方向 ----->
  • 內存的低位 -----> 內存的高位
    01 02 03 04

0x 12 34 56 78 11 22 33 44
在這里插入圖片描述

  • 通過代碼檢測當前主機的字節序
#include <stdio.h>int main() {union {short value;    // 2字節char bytes[sizeof(short)];  // char[2]} test;test.value = 0x0102;if((test.bytes[0] == 1) && (test.bytes[1] == 2)) {printf("大端字節序\n");} else if((test.bytes[0] == 2) && (test.bytes[1] == 1)) {printf("小端字節序\n");} else {printf("未知\n");}return 0;
}

在這里插入圖片描述

2.3 字節序轉換函數

當格式化的數據在兩臺使用不同字節序的主機之間直接傳遞時,接收端必然錯誤的解釋之。

  • 解決問題的方法是:發送端 總是 把要發送的數據 轉換成 大端字節序數據 后再發送,而接收端知道對方傳送過來的數據總是采用大端字節序,所以接收端可以根據自身采用的字節序決定是否對接收到的數據進行轉換(小端機轉換,大端機不轉換)。

????網絡字節順序TCP/IP規定好的 一種數據表示格式,它與具體的 CPU 類型、操作系統等無關,從而可以保證數據在不同主機之間傳輸時能夠被正確解釋,網絡字節順序 采用 大端排序 方式。

?
BSD Socket 提供了封裝好的 轉換接口,方便程序員使用。

  • 包括從 主機字節序網絡字節序轉換函數htonshtonl
  • 網絡字節序主機字節序 的轉換函數:ntohsntohl
h 	- host 主機,主機字節序
to 	- 轉換成什么
n 	- network 網絡字節序
s 	- short : unsigned short   無符號短整型,兩個字節
l 	- long : unsigned int		 無符號長整型,四個字節
#include <arpa/inet.h>
/*網絡通信時,需要將主機字節序轉換成網絡字節序(大端),另外一段獲取到數據以后根據情況將網絡字節序轉換成主機字節序。
*/// 32位,轉IP
uint32_t htonl(uint32_t hostlong);    	// 主機字節序 -> 網絡字節序
uint32_t ntohl(uint32_t netlong); 		// 網絡字節序 -> 主機字節序// 16位,轉換端口
uint16_t htons(uint16_t hostshort); 	// 主機字節序 -> 網絡字節序
uint16_t ntohs(uint16_t netshort);		// 網絡字節序 -> 主機字節序
#include <stdio.h>
#include <arpa/inet.h>int main() {// htonl  轉換IPchar buf[4] = {192, 168, 1, 100};int num = *(int *)buf;int sum = htonl(num);unsigned char *p = (char *)&sum;printf("%d %d %d %d\n", *p, *(p+1), *(p+2), *(p+3));printf("=======================\n");// htons 轉換端口unsigned short a = 0x0102;printf("a : %x\n", a);unsigned short b = htons(a);printf("b : %x\n", b);printf("=======================\n");// ntohl 轉換IPunsigned char buf1[4] = {1, 1, 168, 192};int num1 = *(int *)buf1;int sum1 = ntohl(num1);unsigned char *p1 = (unsigned char *)&sum1;printf("%d %d %d %d\n", *p1, *(p1+1), *(p1+2), *(p1+3));// ntohs 轉換端口return 0;
}

3. socket 地址

?
????socket 地址 其實是一個 結構體,封裝 端口號IP 等信息。 后面的 socket 相關的 api 中需要使用到這個 socket地址

  • 客戶端 -> 服務器IP, Port

3.1 通用 socket 地址

?
????socket 網絡編程接口 中表示 socket 地址 的是 結構體 sockaddr,其定義如下:

#include <bits/socket.h>struct sockaddr {sa_family_t sa_family;	// 地址族類型char sa_data[14]; 		// 14字節
};typedef unsigned short int sa_family_t;		// 2字節

????sa_family 成員是 地址族類型sa_family_t)的 變量地址族類型 通常與 協議族類型 對應。常見的 協議族protocol family,也稱 domain)和對應的 地址族address family) 如下所示:
在這里插入圖片描述
???? PF_*AF_* 都定義在 bits/socket.h 頭文件中,后者前者完全相同的值,所以二者通常混用

????sa_data 成員用于存放 socket 地址值。但是,不同的協議族的地址值具有不同的含義和長度,如下所示:
在這里插入圖片描述

???? 由上表可知,14 字節sa_data 根本無法容納多數協議族的地址值。因此,Linux 定義了下面這個 新的通用的 socket 地址結構體,這個結構體不僅提供了足夠大的空間用于存放地址值,而且是 內存對齊 的。

#include <bits/socket.h>
struct sockaddr_storage
{sa_family_t sa_family;			// 地址族類型unsigned long int __ss_align;	// 內存對齊char __ss_padding[ 128 - sizeof(__ss_align) ];
};typedef unsigned short int sa_family_t;

3.2 專用 socket 地址

???? 很 多網絡編程函數 誕生 早于 IPv4 協議,那時候都使用的是 struct sockaddr 結構體,為了向前兼容,現在 sockaddr 退化成了(void *)的作用,傳遞一個地址 給函數,至于這個函數是 sockaddr_in 還是 sockaddr_in6,由地址族確定,然后函數內部再 強制類型轉化 為所需的地址類型。
在這里插入圖片描述
????UNIX 本地域協議族 使用如下 專用的 socket 地址結構體

#include <sys/un.h>struct sockaddr_un
{sa_family_t sin_family;char sun_path[108];
};

????TCP/IP 協議族sockaddr_insockaddr_in6 兩個專用的 socket 地址結構體,它們分別用于 IPv4IPv6

#include <netinet/in.h>struct sockaddr_in
{sa_family_t sin_family; 		/* __SOCKADDR_COMMON(sin_) 地址族類型*/in_port_t sin_port; 			/* Port number. */struct in_addr sin_addr; 		/* Internet address. *//* Pad to size of `struct sockaddr'.  填充*/unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof (in_port_t) - sizeof (struct in_addr)];
};struct in_addr
{in_addr_t s_addr;
};struct sockaddr_in6
{sa_family_t sin6_family;in_port_t sin6_port; /* Transport layer port # */uint32_t sin6_flowinfo; /* IPv6 flow information */struct in6_addr sin6_addr; /* IPv6 address */uint32_t sin6_scope_id; /* IPv6 scope-id */
};typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef uint16_t in_port_t;
typedef uint32_t in_addr_t;#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))

????所有 專用 socket 地址(以及 sockaddr_storage)類型的變量 在實際使用時都需要轉化通用 socket 地址 類型 sockaddr強制轉化 即可),因為所有 socket 編程接口 使用的地址參數類型都是 sockaddr

4. IP地址轉換(字符串ip -> 整數,主機、網絡字節序的轉換 )

????通常,人們習慣用 可讀性好的字符串 來表示 IP 地址,比如用 點分十進制字符串 表示 IPv4 地址,以及用 十六進制字符串 表示 IPv6 地址。但編程中我們需要先把它們 轉化為 整數(二進制數)方能使用。而記錄日志時則相反,我們要把整數表示的 IP 地址 轉化為 可讀的字符串。下面 3 個函數可用于用 點分十進制字符串 表示的 IPv4 地址 和 用 網絡字節序整數 表示的 IPv4 地址 之間的轉換:

#include <arpa/inet.h>// 下面的這些函數比較久,使用起來比較麻煩,不推薦使用 
in_addr_t inet_addr(const char *cp); 	// 點分十進制字符串 -> 整數
int inet_aton(const char *cp, struct in_addr *inp);	// 點分十進制字符串 -> 整數, 并保存到結構體指針 inp 中
char *inet_ntoa(struct in_addr in); 	// 整數 -> 點分十進制字符串

????下面這對更新的函數也能完成前面 3 個函數同樣的功能,并且它們同時適用 IPv4 地址IPv6 地址:??

#include <arpa/inet.h>// p:點分十進制的IP字符串,n:表示network,網絡字節序的整數
int inet_pton(int af, const char *src, void *dst);af:地址族: AF_INET AF_INET6src:需要轉換的點分十進制的IP字符串dst:轉換后的結果保存在這個里面// 將網絡字節序的整數,轉換成點分十進制的IP地址字符串
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);af:地址族: AF_INET AF_INET6src: 要轉換的ip的整數的地址dst: 轉換成IP地址字符串保存的地方size:第三個參數的大小(數組的大小)返回值:返回轉換后的數據的地址(字符串),和 dst 是一樣的
#include <stdio.h>
#include <arpa/inet.h>int main() {// 創建一個ip字符串,點分十進制的IP地址字符串char buf[] = "192.168.1.4"; // 后面默認還有一個字符串結束符unsigned int num = 0;// 將點分十進制的IP字符串轉換成網絡字節序的整數inet_pton(AF_INET, buf, &num);unsigned char * p = (unsigned char *)&num;printf("%d %d %d %d\n", *p, *(p+1), *(p+2), *(p+3)); // 大端排序// 將網絡字節序的IP整數轉換成點分十進制的IP字符串char ip[16] = "";const char * str =  inet_ntop(AF_INET, &num, ip, 16);printf("str : %s\n", str);printf("ip : %s\n", str);printf("%d\n", ip == str);return 0;
}

在這里插入圖片描述

5. TCP 通信流程

TCPUDP -> 傳輸層的協議

  • UDP: 用戶數據報協議,面向無連接,可以單播,多播,廣播, 面向 數據報,不可靠
  • TCP: 傳輸控制協議,面向連接的,可靠的,基于 字節流僅支持單播傳輸
?UDPTCP
是否創建連接無連接面向連接
是否可靠不可靠可靠的
連接的對象個數一對一、一對多、多對一、多對多支持一對一
傳輸的方式面向數據報面向字節流
首部開銷8個字節最少20個字節
適用場景實時應用(視頻會議,直播)可靠性高的應用(文件傳輸)

在這里插入圖片描述

TCP 通信的流程 ??????
在這里插入圖片描述
??服務器端被動接受連接的角色)??

  1. 創建 一個用于監聽的套接字
    • 監聽:監聽有客戶端的連接
    • 套接字 :這個套接字其實就是一個 文件描述符
  2. 將這個 監聽 文件描述符本地的IP端口 綁定IP端口 就是 服務器的地址信息
    • 客戶端 連接 服務器 的時候使用的就是這個 IP端口
  3. 設置 監聽,監聽的 fd 開始工作
  4. 阻塞等待,當有客戶端發起連接,解除阻塞,接受客戶端的連接,會得到一個 和客戶端通信的 套接字fd
  5. 通信
    • 接收數據
    • 發送數據
  6. 通信結束斷開連接

??客戶端??

  1. 創建一個用于通信的套接字fd
  2. 連接服務器,需要指定連接的服務器IP端口
  3. 連接成功了,客戶端可以直接和服務器 通信
    • 接收數據
    • 發送數據
  4. 通信結束斷開連接

6. 套接字函數

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h> // 包含了這個頭文件,上面兩個就可以省略int socket(int domain, int type, int protocol);- 功能:創建一個套接字- 參數:- domain: 協議族AF_INET : ipv4AF_INET6 : ipv6AF_UNIX, AF_LOCAL : 本地套接字通信(進程間通信)- type: 通信過程中使用的協議類型SOCK_STREAM : 流式協議SOCK_DGRAM : 報式協議- protocol : 具體的一個協議。一般寫0(默認)- SOCK_STREAM : 流式協議默認使用 TCP- SOCK_DGRAM : 報式協議默認使用 UDP- 返回值:- 成功:返回文件描述符,操作的就是內核緩沖區。- 失敗:-1int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); // socket命名- 功能:綁定,將fd 和本地的IP + 端口進行綁定- 參數:- sockfd : 通過socket函數得到的文件描述符- addr : 需要綁定的socket地址,這個地址封裝了ip和端口號的信息- addrlen : 第二個參數結構體占的內存大小int listen(int sockfd, int backlog);  /proc/sys/net/core/somaxconn- 功能:監聽這個socket上的連接- 參數:- sockfd : 通過socket()函數得到的文件描述符- backlog : 未連接的隊列 和 已經連接的隊列 和的最大值(以使用 cat /proc/sys/net/core/somaxconn 查看:4096),一般不用設置那么大,如:128int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);- 功能:接收客戶端連接,默認是一個阻塞的函數,阻塞等待客戶端連接- 參數:- sockfd : 用于監聽的文件描述符- addr : 傳出參數,記錄了連接成功后客戶端的地址信息(ip,port)- addrlen : 指定第二個參數的對應的內存大小- 返回值:- 成功 :用于通信的文件描述符- -1 : 失敗int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);- 功能: 客戶端連接服務器- 參數:- sockfd : 用于通信的文件描述符- addr : 客戶端要連接的服務器的地址信息- addrlen : 第二個參數的內存大小- 返回值:成功 0, 失敗 -1ssize_t write(int fd, const void *buf, size_t count); // 寫數據
ssize_t read(int fd, void *buf, size_t count); // 讀數據

TCP 通信實現

(1)服務器端

????創建 server.c 文件

// TCP 通信的服務器端#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>int main() {// 1.創建socket(用于監聽的套接字)int lfd = socket(AF_INET, SOCK_STREAM, 0);if(lfd == -1) {perror("socket");exit(-1);}// 2.綁定struct sockaddr_in saddr;saddr.sin_family = AF_INET;// inet_pton(AF_INET, "192.168.193.128", saddr.sin_addr.s_addr);saddr.sin_addr.s_addr = INADDR_ANY;  // 0.0.0.0saddr.sin_port = htons(9999);int ret = bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr));if(ret == -1) {perror("bind");exit(-1);}// 3.監聽ret = listen(lfd, 8);if(ret == -1) {perror("listen");exit(-1);}// 4.接收客戶端連接struct sockaddr_in clientaddr;int len = sizeof(clientaddr);int cfd = accept(lfd, (struct sockaddr *)&clientaddr, &len);if(cfd == -1) {perror("accept");exit(-1);}// 輸出客戶端的信息char clientIP[16];inet_ntop(AF_INET, &clientaddr.sin_addr.s_addr, clientIP, sizeof(clientIP));unsigned short clientPort = ntohs(clientaddr.sin_port);printf("client ip is %s, port is %d\n", clientIP, clientPort);// 5.通信char recvBuf[1024] = {0};while(1) {// 獲取客戶端的數據int num = read(cfd, recvBuf, sizeof(recvBuf));if(num == -1) {perror("read");exit(-1);} else if(num > 0) {printf("recv client data : %s\n", recvBuf);} else if(num == 0) {// 表示客戶端斷開連接printf("clinet closed...");break;}char * data = "hello,i am server";// 給客戶端發送數據write(cfd, data, strlen(data));}// 關閉文件描述符close(cfd);close(lfd);return 0;
}

注: 僅供學習參考,如有不足,歡迎指正!

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

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

相關文章

算法------(13)KMP

例題&#xff1a;&#xff08;1&#xff09;AcWing 831. KMP字符串 。。其實寫完也不太理解。。隨便寫點吧 KMP就是求next數組和運用next的數組的過程。相比傳統匹配模式一次更新一單位距離的慢速方法&#xff0c;next數組可以讓下表字符串一次更新n - next【n】個距離&#x…

Java讀取文件

讀取文件為String 、訪問鏈接直接跳轉html 環境&#xff1a;SpringMVC 、前端jsp InputStreamReader FileInputStream fileInputStream new FileInputStream(formatFile.getHtmlpath());InputStreamReader reader new InputStreamReader(fileInputStream, StandardCharsets…

【EAI 026】RoboGen: 通過自動數據生成管線實現機器人技能學習

Paper Card 論文標題&#xff1a;RoboGen: Towards Unleashing Infinite Data for Automated Robot Learning via Generative Simulation 論文作者&#xff1a;Yufei Wang, Zhou Xian, Feng Chen, Tsun-Hsuan Wang, Yian Wang, Zackory Erickson, David Held, Chuang Gan 作者單…

C++:菱形繼承問題

目錄 1、什么是菱形繼承 2、虛擬繼承 3、一些常見問題 1. 什么是菱形繼承&#xff1f;菱形繼承的問題是什么&#xff1f; 2. 什么是菱形虛擬繼承&#xff1f;如何解決數據冗余和二義性的 3. 繼承和組合的區別&#xff1f;什么時候用繼承&#xff1f;什么時候用組合&#…

Qt 自定義長條進度條(類似播放器進度條)

1.運行界面 2.步驟 其實很簡單。 2.1繪制底圖圓角矩形 2.2繪制播放進度圓角矩形 參考&#xff1a;painter繪圖 3.源碼 #pragma once#include <QWidget> #include <QLabel> #include <QHBoxLayout> #include <QMouseEvent> #include <QDebug&g…

Slicer學習筆記(六十五) 3DSlicer的醫學圖像數據增強擴展模塊

1. 醫學圖像數據增強擴展模塊 基于3D Slicer5.1.0 編寫了一個測試醫學圖像的數據增強測試擴展模塊。 擴展模塊名&#xff1a;DataAugementation 項目地址&#xff1a;DataAugmentation 下載該項目后&#xff0c;可以將該擴展模塊添加到3D Slicer的擴展中。 關于如何給3DSlicer…

MySQL數據庫基本操作(一)

數據庫的基本概念 1. 數據庫的英文單詞&#xff1a; DataBase 簡稱 &#xff1a; DB 2. 什么數據庫&#xff1f;* 用于存儲和管理數據的倉庫。 ? 3. 數據庫的特點&#xff1a;1. 持久化存儲數據的。其實數據庫就是一個文件系統2. 方便存儲和管理數據3. 使用了統一的方式操作數…

微信自動回復,基于python

#!/usr/bin/python3 # -*- coding: utf-8 -*-import numpy as np import pandas as pd from uiautomation import WindowControl import csvwx WindowControl(Name微信,searchDepth1 ) # 切換窗口 wx.ListControl() wx.SwitchToThisWindow() # 尋找會話控件綁定 hw wx.…

LaTeX-設置表格大小

文章目錄 LaTeX-設置表格大小1.創建表格2.設置表格的寬度2.1控制表格每一列的寬度2.2控制整個表格的寬度 3.設置表格的外觀4.LaTeX繪制三線表 LaTeX-設置表格大小 本文介紹了LaTeX如何設置表格的大小、改變表格的外觀以及如何繪制三線表。 1.創建表格 在LaTeX中創建表很耗時…

【前端素材】推薦優質后臺管理系統網頁my-Task平臺模板(附源碼)

一、需求分析 1、系統定義 后臺管理系統是一種用于管理網站、應用程序或系統的工具&#xff0c;通常由管理員使用。后臺管理系統是一種用于管理和控制網站、應用程序或系統的管理界面。它通常被設計用來讓網站或應用程序的管理員或運營人員管理內容、用戶、數據以及其他相關功…

2023年NOC大賽軟件創意編程(學而思)賽道圖形化小低高組決賽試題

2023NOC 決賽-小低組 每個小朋友從小會有夢寐以求的愿望,或是擁有孫悟空七十二變的能 力,或是像神筆馬良一樣想要什么畫什么,或是成為人見人愛的國寶 大熊貓,或是變身全能機器人……今天,你可以用編程實現自己愿望! 【題目要求】 請以“假如我是_____”為題,自選主…

Sentinel實戰(待完善)

目錄 服務雪崩 什么是服務雪崩 服務不可用原因 解決方案 技術選型對比 Sentinel 介紹 優點 核心概念 資源 規則 代碼實戰 API實現 SentinelResource注解實現 Sentinel控制臺 啟動控制臺服務 java應用接入控制臺 微服務接入Sentinel 服務雪崩 什么是服務雪崩…

DETR詳解

1. 動機 傳統的目標檢測任務需要大量的人工先驗知識&#xff0c;例如預定義的先驗anchor&#xff0c;NMS后處理策略等。這些人工先驗知識引入了很多人為因素&#xff0c;且較難處理。如果能夠端到端到直接生成目標檢測結果&#xff0c;將會使問題變得很優雅。 2. 主要貢獻 提…

牛客小白月賽87 A-G 題解 | JorbanS

文章目錄 [A - 小苯的石子游戲](https://ac.nowcoder.com/acm/contest/73854/A)[B - 小苯的排序疑惑](https://ac.nowcoder.com/acm/contest/73854/B)[C - 小苯的IDE括號問題&#xff08;easy&#xff09;](https://ac.nowcoder.com/acm/contest/73854/C)[D - 小苯的IDE括號問題…

向爬蟲而生---Redis 探究篇3<`Redis事務`和`Sql事務`區別>

前言: 在數據管理和應用開發中&#xff0c;事務的概念至關重要。事務用于組織和管理一系列對數據進行更新或操作的步驟&#xff0c;確保數據的一致性和可靠性。事務能夠保證在一組相關操作中的原子性、一致性、隔離性和持久性&#xff0c;從而確保數據庫的可靠性。 Redis和My…

idea中maven配置(一次成功,全部細節都有)

寫這篇文章的原因是maven的配置很簡單&#xff0c;但是也很容易出錯&#xff0c;我連配了兩臺電腦的maven出現了各種小錯誤&#xff0c;參考了以下兩篇博文IDEA配置Maven教程&#xff08;超詳細版~)_idea maven配置教程-CSDN博客 一次包會——最新IDEA配置Maven指南&#xff0…

python 基礎知識點(藍橋杯python科目個人復習計劃57)

今日復習計劃&#xff1a;做題 例題1&#xff1a;笨笨的機器人 問題描述&#xff1a; 肖恩有一個機器人&#xff0c;他能根據輸入的指令移動相應的距離。但是這個機器人很笨&#xff0c;他永遠分不清往左邊還是往右邊移動。肖恩也知道這一點&#xff0c;所以他設定這個機器人…

mysql 遠程不允許連接 1130 -Host ‘‘ is not allowed to connect to this MySQL server

1、docker 進入mysql 命令 sudo docker exec -it 0c58 /bin/bash 2、連接mysql mysql -u root -ppwd 3、 use mysql; 4、更改表所有root用戶都可以連接 update user set host ‘%’ where user‘root’; 5、刷新權限 flush privilege&#xff1b; ok解決&#xff1b;

五大跨平臺桌面應用開發框架:Electron、Tauri、Flutter等

hello&#xff0c;我是貝格前端工場&#xff0c;本次介紹跨平臺開發的框架&#xff0c;歡迎大家評論、點贊。 一、什么是跨平臺桌面應用開發框架 跨平臺桌面應用開發框架是一種工具或框架&#xff0c;它允許開發者使用一種統一的代碼庫或語言來創建能夠在多個操作系統上運行的…

3.2日學習打卡----初學FastDFS(二)

3.2日學習打卡 目錄: 3.2日學習打卡SpringBoot整合FastDFS實戰開發文件上傳 FastDFS集成Nginx環境搭建 SpringBoot整合FastDFS 由GitHub大牛tobato在原作者YuQing與yuqih發布的JAVA客戶端基礎上進行了大量重構工作&#xff0c;并于GitHub上發布了FastDFS-Client1.26.5。 主要特…