深入了解UDP套接字:構建高效網絡通信

個人主頁:chian-ocean

文章專欄-NET

深入了解UDP套接字:構建高效網絡通信

    • 個人主頁:chian-ocean
    • 文章專欄-NET
  • 前言:
  • UDP
    • UDP 特點:
    • UDP的應用
  • 套接字地址
    • IP地址(Internet Protocol Address)
      • IP地址的點分十進制表示
    • 端口
      • 端口的作用
      • 知名端口
  • UDP套接字`API`
    • 創建套接字(`socket`)
        • 參數說明:
    • `sockaddr`結構體
    • 網絡字節序(Network Byte Order)
      • 為什么需要網絡字節序?
      • 網絡字節序與主機字節序的區別
      • 網絡字節序和主機字節序的轉換
    • `recvfrom` 和 `sendto` 函數
        • 1. `recvfrom` 函數
        • 參數:
        • 2. `sendto` 函數
        • 參數:
        • 返回值:
  • UDP網絡編程
    • 網絡服務端
      • 代碼結構及功能說明:
    • 網絡客戶端
      • `Linux OS`
        • 代碼結構與功能說明:
      • `WIndows OS`
        • 代碼結構與功能說明:
  • 源碼

前言:

TCP/IP中有兩個具有代表性的傳輸層協議,他們分別是TCP和UDP。TCP提供可靠的通信傳輸,而UDP則經常被用于讓廣播和細節控制交給應用層傳輸。總之,根據通信特征,選擇合適的傳輸層協議是非常重要的。

image-20250607204107474

UDP

UDP(User Datagram Protocol,用戶數據報協議) 是一種簡單的、無連接的網絡協議,屬于傳輸層協議。

UDP 特點:

  • 無連接:UDP 不需要先建立連接(無三次握手過程),每次發送數據時,發送方只需要提供目標地址和端口信息。
  • 不可靠性:UDP 不保證數據包的順序、完整性或可靠性。數據報可能會丟失、重復或亂序。應用層需要自行處理這些問題(如果需要的話)。
  • 面向數據報:每個數據報是獨立的,發送時與接收時無關,不能保證數據順序,也不做數據流的管理。

UDP的應用

  • 包總量較少的通信(DNS,SNMP等)
  • 視頻、音頻等多媒體通信(實時通信)
  • 限定與LAN等特定網絡中的應用通信
  • 廣播通信(廣播、多播)

套接字地址

? 應用在使用TCP或者UDP的時候,會時使用OS提供的類庫,始終庫一般稱作為API(Application Programming Interface,應用程序編程接口)。

? 在使用TCP或者UDP通信的時候,又會廣泛的使用到套接字(socket)的API。套接字原本是BSD UNIX 開發的,后面應用到了Windows的Winsock以及嵌入式操作系統中。

? 應用程序應用套接字,可以設置端口號的IP地址、端口號、并且實現書庫的接受和發送。

image-20250607203527592

IP地址(Internet Protocol Address)

IP 地址(Internet Protocol Address,互聯網協議地址)是計算機網絡中用來唯一標識一臺設備(如計算機、路由器、服務器、打印機等)在網絡中的位置的地址。IP 地址可以類比為每臺計算機的“身份證”,它確保數據在網絡中能夠正確地傳輸到目標設備。

  • IP地址( IPv4地址 ) 由32位正整數來表示。TCP/IP通信要求將這樣的IP地址分配給每一個參與通信的主機。

IP地址的點分十進制表示

IP 地址的點分十進制表示法 是將 IPv4 地址(32 位二進制)分成四個字節(每個字節 8 位),并將每個字節轉換為十進制數,用 點(. 分隔開來。這個格式使得人們更容易理解和記住 IP 地址。

二進制 IP 地址10101100.00010100.00000001.00000001

十進制轉換

  • 10101100172
  • 0000100020
  • 000000011
  • 000000011

image-20250607203531698

端口

在計算機網絡中,端口是用來標識應用程序或網絡服務的數字標識符,它幫助計算機識別不同的網絡服務和應用程序。端口號與 IP 地址 一起構成了唯一的通信標識符,用于網絡中數據包的正確傳遞。

端口的作用

  1. 區分不同的服務和應用程序
    • 計算機網絡中,不同的服務和應用程序通過不同的端口號來區分。每個網絡應用程序都會監聽某個端口,操作系統通過端口號將接收到的數據分配給相應的應用程序。
  2. 實現多路復用
    • 多路復用指的是通過不同的端口號使同一臺計算機能夠同時處理多個網絡連接。比如,Web 服務器通常通過端口 80(HTTP)接收請求,同時,FTP 服務器可以通過端口 21 處理文件傳輸。
  3. 標識網絡協議
    • 端口號與 TCPUDP 等傳輸層協議配合使用,用于區分不同協議的數據流。TCP 和 UDP 使用不同的端口號來處理數據包。

知名端口

端口號的 0 到 1023 范圍是 知名端口,通常由 IANA(互聯網數字分配局)分配并保留給常見的協議和服務。這些端口號通常不允許由普通用戶或應用程序使用,因為它們被特定的系統服務和協議占用。

  • 端口 0:端口 0 是一個特殊的保留端口,通常不能用于正常通信。它通常用于表示 “無效” 或 “未定義的端口”。
  • 端口 1 到 1023:這些端口被廣泛用于操作系統和標準網絡協議,因此普通用戶和應用程序不能使用它們。舉例來說:
    • 22:SSH(安全外殼協議)
    • 80:HTTP(Web 服務)
    • 443:HTTPS(加密的 Web 服務)
    • 25:SMTP(郵件傳輸協議)

在試圖綁定80端口號,會出錯返回(Permission denied)。

image-20250607203540098

UDP套接字API

創建套接字(socket)

image-20250607203543800

int socket(int domain, int type, int protocol);
參數說明:
  • domain:指定協議族,通常使用 AF_INET 表示 IPv4,AF_INET6 表示 IPv6,AF_UNIX 表示 UNIX 域套接字。
  • type:指定套接字類型,通常使用:
    • SOCK_STREAM:流式套接字,適用于 TCP 協議(面向連接)。
    • SOCK_DGRAM:數據報套接字,適用于 UDP 協議(無連接)。
  • protocol:指定協議類型,通常設為 0,表示自動選擇合適的協議。

demo

int sockfd_ = socket(AF_INET,SOCK_DGRAM,0);//創建套接字
if(sockfd_ < 0)
{lg(fatal,"Socket error,errno: %d,error: %s",errno,strerror(errno));//打印日志
}
lg(info,"Socket Success");//打印日志

sockaddr結構體

C 語言 的網絡編程中,sockaddr 是一個結構體,表示網絡通信中的地址信息。它用于存儲與套接字(socket)相關的地址信息,例如 IP 地址和端口號。sockaddr 是一個通用的結構體,用于支持不同類型的地址族(例如 IPv4IPv6Unix 域套接字)的地址。

sockaddr_in(用于 IPv4 地址)

  • sockaddr_insockaddr 的一個擴展,專門用于存儲 IPv4 地址的信息。它包含了 IP 地址、端口號等信息。
struct sockaddr_in {short            sin_family;   // 地址族,通常是 AF_INETunsigned short   sin_port;     // 端口號(網絡字節序)struct in_addr   sin_addr;     // IP 地址(網絡字節序)char             sin_zero[8];  // 填充字節,通常不使用
};

網絡字節序(Network Byte Order)

網絡字節序(Network Byte Order)是指在網絡通信中,數據以 大端字節序(Big Endian) 的格式進行傳輸的約定。它規定了多字節數據(如整數、浮點數等)在傳輸過程中,應該按照高位字節存儲在低地址位置(大端格式),從而確保不同計算機之間的數據傳輸能夠正確解析。

為什么需要網絡字節序?

不同的計算機架構(如 x86PowerPC)使用不同的字節序來存儲多字節數據。常見的字節序有:

  1. 大端字節序(Big Endian):高位字節存儲在內存的低地址位置。
  2. 小端字節序(Little Endian):低位字節存儲在內存的低地址位置。

為了確保網絡中不同架構的計算機能夠正確地交換數據,網絡協議規定所有的數據傳輸必須使用 網絡字節序,即 大端字節序。這使得不同平臺之間的通信可以統一,并避免字節序不一致帶來的數據解釋錯誤。

網絡字節序與主機字節序的區別

  • 主機字節序:是計算機系統內部使用的字節序,依賴于計算機的體系結構。常見的計算機體系結構有:
    • x86/x64 架構:使用小端字節序(Little Endian)。
    • 某些 RISC 架構:可能使用大端字節序(Big Endian)。
  • 網絡字節序:是網絡通信的標準格式,統一為大端字節序。

網絡字節序和主機字節序的轉換

這些函數主要用于將不同字節序的數據進行轉換。由于不同的計算機架構使用不同的字節序(例如,大端字節序和小端字節序),而網絡傳輸規定采用大端字節序(網絡字節序),因此這些函數的作用就是將數據從主機字節序轉換為網絡字節序,或者從網絡字節序轉換為主機字節序。

image-20250607203549767

uint32_t htonl(uint32_t hostlong);//將主機字節序的 32 位長整型轉換為網絡字節序。
uint16_t htons(uint16_t hostshort);//將主機字節序的 16 位短整型轉換為網絡字節序。
uint32_t ntohl(uint32_t netlong);//將網絡字節序的 32 位長整型轉換為主機字節序。
uint16_t ntohs(uint16_t netshort);//將網絡字節序的 16 位短整型轉換為主機字節序。

image-20250607203553238

//將點分十進制的 IPv4 地址字符串(如 `"192.168.1.1"`)轉換為網絡字節序的二進制格式,并存儲在 in_addr 結構體中。
int inet_aton(const char *cp, struct in_addr *inp);//將點分十進制的 IPv4 地址字符串(如 `"192.168.1.1"`)轉換為 32 位的網絡字節序整數格式。
in_addr_t inet_addr(const char *cp);//將點分十進制的網絡地址字符串轉換為網絡字節序的整數(通常是 IP 地址的網絡部分)。
in_addr_t inet_network(const char *cp);//將網絡字節序的二進制格式的 IPv4 地址轉換為點分十進制的字符串格式。
char *inet_ntoa(struct in_addr in);//根據網絡號和主機號生成網絡字節序的完整 IP 地址。
struct in_addr inet_makeaddr(int net, int host);//提取 in_addr 結構體中的主機部分。
in_addr_t inet_lnaof(struct in_addr in);//提取 `in_addr` 結構體中的網絡部分。
in_addr_t inet_netof(struct in_addr in);

recvfromsendto 函數

recvfromsendto 是用于 UDP(無連接協議)原始套接字(raw socket) 的函數,允許應用程序在網絡上傳輸數據。這些函數可以在不同的網絡地址和端口之間進行數據的發送和接收。

1. recvfrom 函數

recvfrom 用于接收來自指定地址的數據包。它不僅接收數據,還能夠獲取數據來源的信息(如發送者的 IP 地址和端口號),非常適用于 UDP原始套接字 通信。

原型

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
參數:
  • sockfd:套接字文件描述符。
  • buf:用于存儲接收到的數據的緩沖區。
  • len:緩沖區的大小。
  • flags:接收的標志位,通常設為 0。
  • src_addr:指向 sockaddr 結構體的指針,接收者的地址信息(如 IP 地址和端口)。
  • addrlensrc_addr 結構體的大小。調用后,addrlen 會被設置為實際填充的地址長度。
2. sendto 函數

sendto 用于向指定的地址和端口發送數據。它通常用于 UDP原始套接字,可以向特定的目標地址發送數據。

原型

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
參數:
  • sockfd:套接字文件描述符。
  • buf:要發送的數據的緩沖區。
  • len:要發送的數據的字節數。
  • flags:發送的標志位,通常設為 0。
  • dest_addr:指向目標地址的 sockaddr 結構體,指定數據包的目標地址和端口。
  • addrlendest_addr 結構體的大小。
返回值:
  • 成功時,返回發送的字節數。
  • 失敗時,返回 -1,errno 會被設置為錯誤代碼。

UDP網絡編程

網絡服務端

#pragma once
#include <iostream>
#include <cstring>
#include <string>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>#include "log.hpp"// 日志對象,用于記錄日志信息
Log lg;// 默認端口號為 8080
#define defaultport 8080
// 默認緩沖區大小為 1024 字節
int size = 1024;
// 默認 IP 地址為 "0.0.0.0",表示監聽所有可用的網絡接口
std::string defaultip = "0.0.0.0";// UdpServer 類定義:用于創建和管理 UDP 服務器
class UdpServer
{
public:// 構造函數,默認套接字文件描述符為 0,默認端口為 8080,默認 IP 為 "0.0.0.0"UdpServer(int sockfd = 0,uint16_t port = defaultport,std::string ip = defaultip):sockfd_(sockfd),port_(port),ip_(ip){}// 初始化服務器:創建套接字,綁定到指定的 IP 和端口void Init(){// 創建 UDP 套接字sockfd_ = socket(AF_INET,SOCK_DGRAM,0);if(sockfd_ < 0){// 如果創建套接字失敗,記錄日志并返回lg(fatal,"Socket error,errno: %d,error: %s",errno,strerror(errno));}lg(info,"Socket Success");// 配置本地地址(IPv4 地址)struct sockaddr_in local;bzero(&local,sizeof(local));  // 將地址結構清零local.sin_family = AF_INET;    // 地址族為 IPv4local.sin_port = htons(port_); // 將端口號轉換為網絡字節序local.sin_addr.s_addr = inet_addr(ip_.c_str()); // 將 IP 地址轉換為網絡字節序// 綁定套接字到指定的地址和端口int n  = bind(sockfd_,(struct sockaddr*)&local,sizeof(local));if(n < 0){// 如果綁定失敗,記錄日志并返回lg(fatal,"Bind error,errno: %d ,errno: %s",errno,strerror(errno));}lg(info,"Bind Success");}// 服務器的主運行函數:接收客戶端消息,并將消息回復給客戶端void Run(){is_running_ = true;while(is_running_){char inbuffer[size]; // 用于接收數據的緩沖區struct sockaddr_in client;  // 客戶端地址信息bzero(&client,sizeof(client));  // 將客戶端地址結構清零socklen_t clientSize = sizeof(client);  // 客戶端地址的長度// 使用 recvfrom 接收客戶端發送的數據ssize_t n = recvfrom(sockfd_,inbuffer,sizeof(inbuffer),0,(struct sockaddr*)&client,&clientSize);if(n < 0){// 如果接收數據失敗,記錄日志并繼續等待其他數據lg(warning,"recvfrom error, errno: %d, err string: %s", errno, strerror(errno));continue;}inbuffer[n] = 0;  // 將接收到的數據字符串終結符設置為 NULLstd::string Info = inbuffer;  // 將接收到的數據轉為字符串std::cout << Info << std::endl; // 輸出接收到的消息// 使用 sendto 發送數據回客戶端sendto(sockfd_,Info.c_str(),Info.size(),0,(struct sockaddr*)&client,sizeof(client)); }}// 析構函數:關閉套接字,釋放資源~UdpServer(){if(sockfd_ > 0) close(sockfd_);}private:int sockfd_;     // 套接字文件描述符uint16_t port_;  // 服務器端口std::string ip_; // 服務器 IP 地址bool is_running_ = false;  // 服務器運行狀態
};

代碼結構及功能說明:

  1. 構造函數:初始化類的成員變量,包括套接字文件描述符、端口號和 IP 地址。默認值為端口 8080 和 IP 地址 0.0.0.0,這意味著它將綁定到所有可用的網絡接口。
  2. Init():初始化函數,用于創建 UDP 套接字并綁定到指定的 IP 地址和端口。如果創建套接字或綁定失敗,函數會記錄錯誤日志并停止執行。
  3. Run():主循環函數,服務器在此函數中運行。它不斷接收客戶端的消息,并將接收到的消息發送回客戶端。數據是通過 recvfrom()sendto() 函數進行接收和發送的。
  4. ~UdpServer():析構函數,用于關閉套接字,釋放相關資源。

網絡客戶端

Linux OS

#include <iostream>
#include <cstring>
#include <string>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>#include "log.hpp"// 創建一個日志對象,用于記錄日志信息
Log lg;// 緩沖區大小設為 1024 字節
size_t size = 1024;// 使用說明函數,顯示如何使用客戶端程序
void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " serverip serverport\n"<< std::endl;
}int main(int argc ,char* argv[])
{// 參數檢查:需要兩個參數,服務器的 IP 地址和端口號if(argc != 3){Usage(argv[0]);return 1;}// 從命令行參數獲取 IP 地址和端口號std::string ip = argv[1];    std::uint16_t port = std::stoi(argv[2]);  // 將端口號從字符串轉換為整數// 配置服務器的 sockaddr_in 結構體struct sockaddr_in server;bzero(&server,sizeof(server));   // 清空結構體server.sin_family = AF_INET;      // 地址族為 IPv4server.sin_port = htons(port);   // 端口號轉換為網絡字節序server.sin_addr.s_addr = inet_addr(ip.c_str());  // 將 IP 地址轉換為網絡字節序// 創建 UDP 套接字int sockfd = socket(AF_INET,SOCK_DGRAM,0);if(sockfd < 0){// 如果套接字創建失敗,記錄日志并返回lg(fatal,"sock error: errno:%d,error:%s",errno,strerror(errno));return 1;}lg(info,"sock success");  // 創建套接字成功std::string message;  // 存儲用戶輸入的消息while(true){message.clear();  // 清空消息內容std::cout << "Please Enter@: ";  // 提示用戶輸入getline(std::cin, message);  // 獲取用戶輸入// 配置臨時的客戶端地址結構struct sockaddr_in tmp;bzero(&tmp,sizeof(tmp));  // 清空結構體socklen_t tmplen = sizeof(tmp);// 發送數據到服務器sendto(sockfd, message.c_str(), size, 0, (struct sockaddr*)&server, sizeof(server));// 接收服務器的響應char buffer[size];  // 接收數據的緩沖區ssize_t s = recvfrom(sockfd, &buffer, sizeof(buffer) - 1, 0, (struct sockaddr*)&tmp, &tmplen);if(s > 0){buffer[s] = '\0';  // 確保接收到的數據以 NULL 終結std::cout << buffer << std::endl;  // 輸出服務器的響應}}  // 關閉套接字close(sockfd);return 0;
}
代碼結構與功能說明:
  1. Usage() 函數:如果程序沒有正確傳入 IP 地址和端口號參數,該函數會提示用戶如何使用該程序。它顯示了程序的運行方式。
  2. main() 函數
    • 命令行參數處理:獲取用戶輸入的服務器 IP 地址和端口號。
    • server 配置:創建并配置 sockaddr_in 結構體來存儲服務器的地址信息(IP 地址和端口)。
    • 套接字創建:使用 socket() 創建一個 UDP 套接字。如果創建失敗,則記錄錯誤并退出。
    • sendto()recvfrom()
      • sendto() 用于將消息發送到服務器。
      • recvfrom() 用于接收從服務器返回的數據。接收到的數據會被存儲在 buffer 中,并輸出到終端。
  3. UDP 套接字
    • 客戶端不需要調用 bind() 來綁定端口,因為 UDP 是無連接的。發送數據時,UDP 套接字會自動選擇一個臨時端口。
  4. 消息發送與接收
    • 用戶輸入的消息通過 sendto() 發送到服務器。
    • 程序等待并接收服務器的響應,通過 recvfrom() 來獲取數據,成功接收數據后輸出。
  5. 日志系統
    • 代碼使用 Log 類記錄重要的信息、錯誤、成功狀態等,便于調試和追蹤。

WIndows OS

//#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>  // 包含 Winsock2 庫,用于套接字編程
#include <Windows.h>   // 包含 Windows API,提供操作系統相關的功能
#include <iostream>    // 包含輸入輸出流庫,用于顯示信息
#include <string>      // 包含字符串操作函數
#include <cstring>     // 包含字符串處理函數#pragma warning(disable:4996)  // 禁用有關不推薦使用的函數的編譯器警告
#pragma comment(lib, "ws2_32.lib")  // 鏈接 Winsock 庫,確保使用 Winsock 2.2 APIint main() {std::cout << "hello client" << std::endl;  // 輸出客戶端信息WSADATA wsaData;  // 用于存儲 Winsock 初始化數據SOCKET udpSocket;  // 用于存儲創建的 UDP 套接字sockaddr_in serverAddr;  // 用于存儲服務器的地址信息int len = sizeof(serverAddr);  // 地址結構的大小const char* serverIP = "119.3.219.187";  // 服務器的 IP 地址int serverPort = 8080;  // 服務器的端口號// 初始化 Winsock 庫if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {std::cerr << "Winsock initialization failed!" << std::endl;  // 如果初始化失敗,輸出錯誤信息return 1;}// 創建 UDP 套接字udpSocket = socket(AF_INET, SOCK_DGRAM, 0);  // 使用 IPv4 地址族和 UDP 協議if (udpSocket == INVALID_SOCKET) {  // 如果創建套接字失敗std::cerr << "Socket creation failed!" << std::endl;WSACleanup();  // 清理 Winsock 庫資源return 1;}// 配置服務器的地址信息serverAddr.sin_family = AF_INET;  // 地址族設置為 IPv4serverAddr.sin_port = htons(serverPort);  // 將端口號轉換為網絡字節序serverAddr.sin_addr.s_addr = inet_addr(serverIP);  // 將服務器 IP 地址轉換為網絡字節序// 發送數據std::string message;  // 用于存儲用戶輸入的消息while (true){// 獲取用戶輸入的消息std::cout << "Please Enter#: ";getline(std::cin, message);  // 從標準輸入讀取消息struct sockaddr_in tmp;  // 臨時結構體,用于接收數據int tmplen = sizeof(tmp);  // 地址結構的大小// 使用 sendto 函數發送 UDP 數據包到指定的服務器地址和端口sendto(udpSocket, message.c_str(), message.size(), 0, (struct sockaddr*)&serverAddr, len);// 接收來自服務器的響應char buffer[1024];  // 用于存儲接收到的數據int s = recvfrom(udpSocket, buffer, sizeof(buffer) - 1, 0, (struct sockaddr*)&tmp, &tmplen);  // 接收數據if (s > 0)  // 如果接收到數據{buffer[s] = '\0';  // 確保接收到的字符串以 NULL 終止std::cout << buffer << std::endl;  // 輸出接收到的消息}}std::cout << "Message sent to server!" << std::endl;  // 輸出消息已發送的提示信息// 清理資源,關閉套接字并清理 Winsock 庫closesocket(udpSocket);WSACleanup();return 0;
}
代碼結構與功能說明:
  1. 初始化 Winsock 庫
    • 使用 WSAStartup() 初始化 Winsock 庫,初始化失敗時輸出錯誤信息并退出程序。
  2. 創建 UDP 套接字
    • 使用 socket() 創建一個 UDP 套接字。若創建失敗,則輸出錯誤信息并退出。
  3. 配置服務器地址
    • 設置服務器的地址族為 AF_INET(IPv4 地址族),將端口號轉換為網絡字節序,并將服務器的 IP 地址轉換為網絡字節序。
  4. 發送數據
    • 程序進入一個無限循環,等待用戶輸入消息并發送給服務器。用戶輸入的消息通過 sendto() 發送到指定的服務器地址和端口。
  5. 接收數據
    • 使用 recvfrom() 接收服務器返回的響應。接收到的數據存儲在緩沖區 buffer 中,然后輸出到終端。
  6. 資源清理
    • 使用 closesocket() 關閉套接字,使用 WSACleanup() 清理 Winsock 庫資源。

源碼

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

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

相關文章

C++課設:實現簡易文件加密工具(凱撒密碼、異或加密、Base64編碼)

名人說&#xff1a;路漫漫其修遠兮&#xff0c;吾將上下而求索。—— 屈原《離騷》 創作者&#xff1a;Code_流蘇(CSDN)&#xff08;一個喜歡古詩詞和編程的Coder&#x1f60a;&#xff09; 專欄介紹&#xff1a;《編程項目實戰》 目錄 一、初識文件加密&#xff1a;為什么需要…

Qt/C++學習系列之Excel使用記錄

Qt/C學習系列之Excel使用記錄 前言The process was ended forcefully.解決方式斷點查語句問題 總結 前言 在項目中解析條目達50多條&#xff0c;并且都需要將對應的結果進行顯示。為了將結果顯示的更加清晰&#xff0c;考慮采用QTableWidget進行表格設置&#xff0c;而在使用過…

Mac軟件卸載指南,簡單易懂!

剛和Adobe分手&#xff0c;它卻總在Library里給你寫"回憶錄"&#xff1f;卸載的Final Cut Pro像電子幽靈般陰魂不散&#xff1f;總是會有殘留文件&#xff0c;別慌&#xff01;這份Mac軟件卸載指南&#xff0c;將用最硬核的方式教你"數字分手術"&#xff0…

并發編程實戰(生產者消費者模型)

在并發編程中使用生產者和消費者模式能夠解決絕大多數的并發問題。該模式通過平衡生產線程和消費線程的工作能力來提高程序整體處理數據的速度。 生產者和消費者模式&#xff1a; 在線程的世界中生產者就是產生數據的線程&#xff0c;而消費者則是消費數據的線程。在多線程開…

力扣hot100---152.乘積最大子數組

給你一個整數數組 nums &#xff0c;請你找出數組中乘積最大的非空連續子數組&#xff08;該子數組中至少包含一個數字&#xff09;&#xff0c;并返回該子數組所對應的乘積。 測試用例的答案是一個 32-位 整數。 示例 1: 輸入: nums [2,3,-2,4] 輸出:6解釋: 子數組 [2,3] 有最…

什么是DevOps智能平臺的核心功能?

在數字化轉型的浪潮中&#xff0c;DevOps智能平臺已成為企業提升研發效能、加速產品迭代的核心工具。然而&#xff0c;許多人對“DevOps智能平臺”的理解仍停留在“自動化工具鏈”的表層概念。今天&#xff0c;我們從一個真實場景切入&#xff1a;假設你是某互聯網公司的技術負…

柯尼卡美能達Konica Minolta bizhub 205i打印機信息

基本參數 產品類型&#xff1a;激光數碼復合機顏色類型&#xff1a;黑白涵蓋功能&#xff1a;復印、打印、掃描最大原稿尺寸&#xff1a;A3內存容量&#xff1a;256MB供紙容量&#xff1a;標配 350 頁&#xff0c;最大 1350 頁介質重量&#xff1a;標準紙盒 64-157g/㎡&#xf…

虛擬機與宿主機應用通信配置指南

1. 選擇虛擬機網絡模式 橋接模式 (Bridged) 客戶機獲得獨立局域網IP&#xff0c;與宿主機同網段。 客戶機可直接訪問宿主機IP&#xff08;如 192.168.1.x&#xff09;。 Host-Only 模式 僅宿主機與客戶機之間通信&#xff0c;宿主機通常有一個虛擬網卡&#xff08;如 192.16…

網絡庫libhv介紹

libhv是一個類似于libevent、libev、libuv的跨平臺網絡庫&#xff0c;提供了更易用的接口和更豐富的協議&#xff0c;用來開發TCP/UDP/SSL/HTTP/WebSocket/MQTT 客戶端/服務端。源碼地址&#xff1a;https://github.com/ithewei/libhv&#xff0c;最新發布版本為v1.3.3&#xf…

施耐德特價型號伺服電機VIA0703D31A1022、常見故障

?? ?一、啟動類故障? ?電機無法啟動? ?可能原因?&#xff1a;電源未接通、制動器未釋放、接線錯誤或控制器故障。?解決措施?&#xff1a; 檢查電源線路及斷路器狀態&#xff1b;驗證制動器是否打開&#xff08;帶制動器型號&#xff09;&#xff1b;核對電機與控制器…

【Redis從入門到精通實戰文章匯總】

&#x1f4da;博客主頁&#xff1a;代碼探秘者 ?專欄&#xff1a;文章正在持續更新ing… ?C語言/C&#xff1a;C&#xff08;詳細版&#xff09; 數據結構&#xff09; 十大排序算法 ?Java基礎&#xff1a;JavaSE基礎 面向對象大合集 JavaSE進階 Java版數據結構JDK新特性…

MCP 技術完全指南:微軟開源項目助力 AI 開發標準化學習

引言 在人工智能快速發展的今天&#xff0c;如何讓 AI 模型與客戶端應用程序之間建立標準化的交互機制&#xff0c;已成為開發者們亟待解決的關鍵問題。微軟近期開源的 mcp-for-beginners 項目&#xff0c;為我們提供了一個系統性學習 Model Context Protocol (MCP) 的絕佳機會…

SQL進階之旅 Day 20:鎖與并發控制技巧

【JDK21深度解密 Day 20】鎖與并發控制技巧 文章簡述 在高并發的數據庫環境中&#xff0c;鎖與并發控制是保障數據一致性和系統穩定性的核心機制。本文作為“SQL進階之旅”系列的第20天&#xff0c;深入探討SQL中的鎖機制、事務隔離級別以及并發控制策略。文章從理論基礎入手…

Qt(part 2)1、Qwindow(菜單欄,工具欄,狀態欄),鉚接部件,核心部件 ,2、添加資源文件 3、對話框

1、Qwindow tips&#xff1a;1&#xff0c;首先為什么創建出的對象基本都是指針形式&#xff0c;個人覺得是對象樹的原因&#xff08;自動釋放內存&#xff09;&#xff0c;指針來訪問成員函數->的形式。2&#xff0c;菜單欄只能一個的&#xff0c;放窗口基本Set&#xff0c…

一款“短小精悍的”手機錄屏軟件

這個時代&#xff0c;手機自帶錄屏功能已經不是什么稀奇的事情了&#xff0c;但是手機自帶的錄屏功能不都是完美的&#xff0c;無法靜音錄屏、、不能修改畫質、不能剪輯、不能自定義水印......emmm.....貌似除了錄屏就什么都不會 今天分享的這款軟件——ADV屏幕錄制漢化版&…

力扣HOT100之二分查找:153. 尋找旋轉排序數組中的最小值

這道題是上一道題&#xff1a;33. 搜索旋轉排序數組的前置題&#xff0c;有點沒看懂力扣為什么要這樣安排題目順序&#xff0c;應該把這道題按排在前面才對啊。。。這道題的思路已經在上一道題的思路中說過了&#xff0c;這里就直接復制粘貼上一篇博客中的內容了。 我們閱讀完題…

libiec61850 mms協議異步模式

之前項目中使用到libiec61850庫&#xff0c;都是服務端開發。這次新的需求要接收服務端的遙測數據&#xff0c;這就涉及到客戶端開發了。 客戶端開發沒搞過啊&#xff0c;挑戰不少&#xff0c;但是人不就是通過戰勝困難才成長的嘛。通過查看libiec61850的客戶端API發現&#xf…

【 知你所想 】基于ernie-x1-turbo推理模型實現趣味猜心游戲

&#x1f31f; 項目特點 &#x1f916; 智能AI&#xff1a;基于文心一言大模型&#xff0c;具有強大的推理能力&#x1f3af; 實時思考&#xff1a;展示AI的思考過程&#xff0c;讓你了解AI是如何推理的&#x1f3ae; 互動性強&#xff1a;通過簡單的"是/否"問答&…

Excel 模擬分析之單變量求解簡單應用

正向求解 利用公式根據貸款總額、還款期限、貸款利率&#xff0c;求每月還款金額 反向求解 根據每月還款能力&#xff0c;求最大能承受貸款金額 參數&#xff1a; 目標單元格&#xff1a;求的值所在的單元格 目標值&#xff1a;想要達到的預期值 可變單元格&#xff1a;變…

關于easyexcel動態下拉選問題處理

前些日子突然碰到一個問題&#xff0c;說是客戶的導入文件模版想支持部分導入內容的下拉選&#xff0c;于是我就找了easyexcel官網尋找解決方案&#xff0c;并沒有找到合適的方案&#xff0c;沒辦法只能自己動手并分享出來&#xff0c;針對Java生成Excel下拉菜單時因選項過多導…