C++高頻知識點(十九)

文章目錄

  • 91. TCP斷開連接的時候為什么必須4次而不是3次?
  • 92. 為什么要區分用戶態和內核態?
  • 93. 說說編寫socket套接字的步驟
    • 1. 服務器端編寫步驟
      • 1.1 創建套接字
      • 1.2 綁定套接字
      • 1.3 監聽連接
      • 1.4 接受連接
      • 1.5 數據傳輸
      • 1.6 關閉套接字
    • 2. 客戶端編寫步驟
      • 2.1 創建套接字
      • 2.2 連接服務器
      • 2.3 數據傳輸
      • 2.4 關閉套接字
  • 94. 什么是大小端模式,編寫代碼區分大小端
    • 如何檢查自己的電腦 是大端還是小端?
      • 第一種方法:
      • 第二種方法:
  • 95. 代碼實現:實現簡單的智能指針

91. TCP斷開連接的時候為什么必須4次而不是3次?

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

92. 為什么要區分用戶態和內核態?

在這里插入圖片描述
在這里插入圖片描述

93. 說說編寫socket套接字的步驟

在這里插入圖片描述
編寫一個基于套接字(socket)的網絡程序通常包括以下步驟,無論是客戶端還是服務器都需要遵循這些步驟。下面分別說明服務器和客戶端編寫的步驟,這些是簡單的代碼示例,僅僅幫助大家去理解這個過程。

1. 服務器端編寫步驟

1.1 創建套接字

使用 socket() 函數創建一個套接字。這個函數返回一個套接字描述符,用于后續的操作。

int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {perror("socket failed");exit(EXIT_FAILURE);
}

1.2 綁定套接字

將創建的套接字綁定到指定的 IP 地址和端口號上,使用 bind() 函數。

struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {perror("bind failed");close(server_fd);exit(EXIT_FAILURE);
}

網絡字節序是大端模式
在這里插入圖片描述
address.sin_addr.s_addr = INADDR_ANY;指綁定端口到本地所有網絡接口
在這里插入圖片描述

1.3 監聽連接

使用 listen() 函數使套接字進入監聽狀態,等待客戶端連接請求。

if (listen(server_fd, 3) < 0) {perror("listen");close(server_fd);exit(EXIT_FAILURE);
}

1.4 接受連接

使用 accept() 函數接受客戶端的連接請求,返回一個新的套接字描述符,用于與客戶端通信。

int new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);
if (new_socket < 0) {perror("accept");close(server_fd);exit(EXIT_FAILURE);
}

1.5 數據傳輸

使用 read() 和 write() 函數(或 recv() 和 send() 函數)進行數據的接收和發送。

char buffer[1024] = {0};
read(new_socket, buffer, 1024);
printf("Message from client: %s\n", buffer);
send(new_socket, "Hello from server", strlen("Hello from server"), 0);

1.6 關閉套接字

完成通信后,使用 close() 函數關閉套接字。

close(new_socket);
close(server_fd);

2. 客戶端編寫步驟

2.1 創建套接字

與服務器端類似,使用 socket() 函數創建一個套接字。

int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {perror("socket failed");exit(EXIT_FAILURE);
}

2.2 連接服務器

使用 connect() 函數將套接字連接到服務器端的指定 IP 地址和端口號。

struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {perror("Invalid address/ Address not supported");close(sock);exit(EXIT_FAILURE);
}if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {perror("Connection Failed");close(sock);exit(EXIT_FAILURE);
}

2.3 數據傳輸

同樣使用 read() 和 write() 或 recv() 和 send() 進行數據的發送和接收。

send(sock, "Hello from client", strlen("Hello from client"), 0);
char buffer[1024] = {0};
read(sock, buffer, 1024);
printf("Message from server: %s\n", buffer);

2.4 關閉套接字

完成通信后,使用 close() 函數關閉套接字。

close(sock);

94. 什么是大小端模式,編寫代碼區分大小端

在這里插入圖片描述
在這里插入圖片描述

如何檢查自己的電腦 是大端還是小端?

第一種方法:

#include <iostream>  bool isLittleEndian() {  int num = 1;  // 數值 1 的 32 位表示是:0x00 00 00 01(從高到低 4 個字節)。// 大端(big-endian)把最高有效字節放在最低地址,所以內存從低地址到高地址是:// 00 00 00 01// 于是 reinterpret_cast<char*>(&num) 指向的第一個字節就是 0x00// 小端(little-endian)相反,把最低有效字節放在最低地址,所以是:// 01 00 00 00// 這時第一個字節是 0x01// 換個更形象的例子:如果 num = 0x12 34 56 78,// 大端內存排布(低→高地址):12 34 56 78// 小端內存排布(低→高地址):78 56 34 12char *c = reinterpret_cast<char*>(&num);  return *c == 1; // 如果最低有效字節在最低地址處,則為小端字節序  
}  int main() {  if (isLittleEndian()) {  std::cout << "This is a little-endian system." << std::endl;  } else {  std::cout << "This is a big-endian system." << std::endl;  }  return 0;  
}

在這里插入圖片描述

第二種方法:

利用數據類型的存儲方式來判斷當前系統的字節序。常見的實現方法是使用 union 聯合體來共享內存,并通過訪問不同的成員來檢查數據的存儲順序。

#include <iostream>
#include <cstdint>// 定義一個聯合體,包含一個整數和一個字符數組
// 聯合體(union)的所有成員共享同一段內存;寫一個成員,換個成員讀,能看到相同內存里的原始字節
union {// uint8_t:精確 8 位 無符號整數,范圍 0 ~ 255。// uint32_t:精確 32 位 無符號整數,范圍 0 ~ 4,294,967,295。uint32_t i;      // 32 位整數uint8_t c[4];    // 4 字節字符數組
} test;int main() {test.i = 0x12345678;  // 將一個已知的 32 位整數存入聯合體中// 根據第一個字節的值判斷大小端if (test.c[0] == 0x78) {std::cout << "小端模式 (Little-endian)" << std::endl;} else if (test.c[0] == 0x12) {std::cout << "大端模式 (Big-endian)" << std::endl;} else {std::cout << "無法確定字節序" << std::endl;}return 0;
}

在這里插入圖片描述

在這里插入圖片描述

95. 代碼實現:實現簡單的智能指針

下面是一個簡單的智能指針實現的例子,用于管理動態分配的內存,避免內存泄漏。這個示例實現了一個類似于 std::shared_ptr 的簡單智能指針,叫做 SimpleSmartPointer,它使用引用計數來管理對象的生命周期。

是在定義一個新對象 sp2,帶著一個“初始值”sp1。
在 C++ 里,帶初始值的定義叫“拷貝初始化(copy-initialization)”,它會調用拷貝構造函數(或能匹配的移動構造),不會調用賦值運算符。賦值運算符只在對象已經存在之后再用 = 給它“換內容”時才會被調用。SimpleSmartPointer<int> a(new int(10));// 1) 拷貝初始化:調用拷貝構造函數
SimpleSmartPointer<int> b = a;     // == SimpleSmartPointer<int> b(a);// 2) 直接初始化:也調用拷貝構造函數
SimpleSmartPointer<int> c(a);// 3) 先默認構造一個對象,再賦值:調用賦值運算符 operator=
SimpleSmartPointer<int> d;         // 等價于 SimpleSmartPointer<int> d(nullptr);
d = a;                             // 這里才會走你的 operator=
#include <iostream>// 簡單智能指針類
template<typename T>
class SimpleSmartPointer {
private:T* ptr;          // 原生指針unsigned* count; // 引用計數public:// 構造函數,接受一個原生指針//這個explicit 主要目的是防止隱式類型轉換。提高代碼可讀性和安全性explicit SimpleSmartPointer(T* p = nullptr) : ptr(p) {if (p) {count = new unsigned(1); // 初始化引用計數為1} else {count = nullptr;}}// 拷貝構造函數SimpleSmartPointer(const SimpleSmartPointer<T>& sp) : ptr(sp.ptr), count(sp.count) {if (count) {(*count)++; // 增加引用計數}}// 賦值運算符重載SimpleSmartPointer<T>& operator=(const SimpleSmartPointer<T>& sp) {if (this == &sp) {return *this; // 防止自我賦值}// 釋放當前資源//--(*count):對 *count(引用計數值)進行自減操作,表示當前對象不再使用該資源//如果 *count 為 0,說明已經沒有其他智能指針對象在使用這個資源了,此時需要釋放資源if (count && --(*count) == 0) {delete ptr;delete count;}// delete ptr; 釋放的是 ptr 指向的那塊堆內存(并調用析構),并不會“刪掉變量 ptr 本身”// 賦值新資源ptr = sp.ptr;count = sp.count;if (count) {(*count)++;}return *this;}// 解引用運算符重載// 返回類型:對 T 的引用。有了引用返回,*sp 就是一個可當左值用的對象(能讀也能改)。// 函數名是個特殊運算符函數:重載“一元解引用運算符 *”。// 調用方式:*sp 等價于 sp.operator*()// operator* 是運算符重載函數,重載的是“一元解引用運算符 *”(注意不是乘法;乘法是二元 *)。// 這是一個成員函數,當你寫 *sp 時,編譯器會把它當作:// sp.operator*()   // 調用你這個函數// ptr 是你類里存的裸指針(T*)。// *ptr 是對這個裸指針的解引用,得到“那個 T 對象本身”。結合返回類型 T&,就把“托管對象”的引用交給了調用者。T& operator*() const {return *ptr;}// 指針訪問運算符重載// T* operator->() const { return ptr; }// 把內部的裸指針 ptr(類型 Point*)拿出來,然后再用普通指針的 -> 去調用 print() / move() / 訪問 x、y。所以 p->成員 就能像真指針那樣用起來了// 前提是裸指針對應的數據結構里面有定義成員變量或者成員函數// operator->() 只有在 T 有成員時才有用;你現在用的是 SimpleSmartPointer<int>,int 沒成員,所以用不上。給它換個有成員的類型,比如 Point,就能直接寫 sp->成員/方法 了。T* operator->() const {return ptr;}// 返回當前共享計數;空指針時按慣例返回 0unsigned use_count() const {return count ? *count : 0;}// 獲取原生指針T* get() const {return ptr;}// 析構函數 RAII~SimpleSmartPointer() {if (count && --(*count) == 0) {delete ptr;delete count;}}
};// 測試函數
void testSimpleSmartPointer() {// sp1.ptr 指向“int(10)”;// sp1.count 指向一塊 unsigned,其值 *count == 1SimpleSmartPointer<int> sp1(new int(10));  // 創建一個智能指針,管理整數10std::cout << "sp1: " << *sp1 << std::endl; // 輸出sp1所指向的值std::cout << "sp1.use_count() = " << sp1.use_count() << "\n";{// 拷貝構造函數  ← 就是被 “SimpleSmartPointer<int> sp2 = sp1;” 調用的這個SimpleSmartPointer<int> sp2 = sp1;    // sp2與sp1共享同一塊內存*sp2 = 33;std::cout << "sp2: " << *sp2 << std::endl; // 輸出sp2所指向的值std::cout << "sp2.use_count() = " << sp2.use_count() << "\n";std::cout << "sp1.use_count() = " << sp1.use_count() << "\n";} // sp2超出作用域,引用計數減1// 再次輸出sp1所指向的值std::cout << "sp1: " << *sp1 << std::endl;std::cout << "sp1.use_count() = " << sp1.use_count() << "\n";
}int main() {testSimpleSmartPointer();return 0;
}

在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述

之后我會持續更新,如果喜歡我的文章,請記得一鍵三連哦,點贊關注收藏,你的每一個贊每一份關注每一次收藏都將是我前進路上的無限動力 !!!↖(▔▽▔)↗感謝支持!

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

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

相關文章

一個基于 epoll 實現的多路復用 TCP 服務器程序,相比 select 和 poll 具有更高的效率

/*5 - 使用epoll實現多路復用 */ #include <stdio.h> // 標準輸入輸出函數庫 #include <stdlib.h> // 標準庫函數&#xff0c;包含exit等 #include <string.h> // 字符串處理函數 #include <unistd.h> // Unix標準函…

元數據管理與數據治理平臺:Apache Atlas 通知和業務元數據 Notifications And Business Metadata

文中內容僅限技術學習與代碼實踐參考&#xff0c;市場存在不確定性&#xff0c;技術分析需謹慎驗證&#xff0c;不構成任何投資建議。Apache Atlas 框架是一套可擴展的核心基礎治理服務&#xff0c;使企業能夠有效、高效地滿足 Hadoop 中的合規性要求&#xff0c;并支持與整個企…

rem:CSS中的相對長度單位

&#x1f90d; 前端開發工程師、技術日更博主、已過CET6 &#x1f368; 阿珊和她的貓_CSDN博客專家、23年度博客之星前端領域TOP1 &#x1f560; 牛客高級專題作者、打造專欄《前端面試必備》 、《2024面試高頻手撕題》、《前端求職突破計劃》 &#x1f35a; 藍橋云課簽約作者、…

【10】C#實戰篇——C# 調用 C++ dll(C++ 導出函數、C++導出類)

文章目錄1 導出C 類函數 、導出 C函數1.1 .h文件1.2 .cpp 文件1.3 C# 調用2 C與C#數據類型對應3 保姆級教程&#xff08;項目搭建、代碼、調用&#xff0c;圖文并茂&#xff09;1 導出C 類函數 、導出 C函數 C 生成動態庫.dll 詳細教程&#xff1a; C 生成動態庫.dll 及 C調用…

Flutter 與 Android NDK 集成實戰:實現高性能原生功能

Flutter 與 NDK 集成實現 Flutter 可以通過 Platform Channels 與原生代碼&#xff08;包括使用 NDK 編寫的 C/C 代碼&#xff09;進行交互。以下是實現 Flutter 與 NDK 集成的步驟&#xff1a; 基本步驟 1. 創建 Flutter 項目 flutter create flutter_ndk_example cd flutter_…

elementui cascader 遠程加載請求使用 選擇單項等

背景&#xff1a;小程序與后端使用自定義表單渲染視圖。發現若沒有全選&#xff08;如&#xff1a;省市縣全部選擇&#xff0c;指定的市3級&#xff09;在pc端就會無法渲染出已經選擇的區縣名稱。 解決方案&#xff1a;參考官方文檔&#xff0c;設置屬性可獨立勾選element ui c…

Unity WebGL打包后啟動方法,本地方法

引言&#xff1a;常見WebGL開啟方法常需要重新打包點擊Build and Run或者將游戲放到Unity的云服務器上&#xff0c;作為開發者而言這兩個方案一個為了開啟再次打包&#xff0c;另一個直接放到了公開環境都不太合適。所以我們需要一個能在本地開啟測試的WebGL的方法。 解決方案 …

安全引導功能及ATF的啟動過程(五)

安全引導功能及ATF的啟動過程&#xff08;五&#xff09; ATF中bl32的啟動 bl31中的runtime_svc_init函數會初始化OP-TEE對應的服務&#xff0c;通過調用該服務項的初始化函數來完成OP-TEE的啟動。對于OP-TEE的服務項會通過DECLARE_RT_SVC宏在編譯時被存放到rt_svc_des段中。該…

Numpy科學計算與數據分析:Numpy入門之多平臺安裝與基礎環境配置

Numpy環境搭建與基礎操作 學習目標 本課程將指導學員在Windows、macOS和Linux三種操作系統上安裝Numpy&#xff0c;并配置開發環境&#xff0c;包括使用Jupyter Notebook和Spyder等IDE的基本操作。通過本課程的學習&#xff0c;學員將能夠獨立搭建Numpy開發環境&#xff0c;并…

內存溢出的原因有哪些,如何排查線上問題?

1. java.lang.OutOfMemoryError: ......java heap space..... 堆棧溢出&#xff0c;代碼問題的可能性極大 2. java.lang.OutOfMemoryError: GC over head limit exceeded 系統處于高頻的GC狀態&#xff0c;而且回收的效果依然 不佳的情況&#xff0c;就會開始報這個錯誤&…

Cesium 無人機視角飛行漫游,截屏

1.實現Cesium模擬無人機離屏渲染&#xff0c;無人機視角飛行漫游。視錐體顯示 具體效果如下地址&#xff1a; 【CESIUM無人機視角飛行截屏】 https://www.bilibili.com/video/BV1zQ89zGE14/?share_sourcecopy_web&vd_source8239ec37df07d6a5d56c9ece00146783

vscode 打開設置

目錄 方法 1&#xff08;快捷鍵&#xff09;&#xff1a; 方法2&#xff0c;界面操作&#xff0c;有時沒有 方法 1&#xff08;快捷鍵&#xff09;&#xff1a; 按下&#xff1a;Cmd Shift P 輸入并選擇&#xff1a;Preferences: Open Settings (JSON) 方法2&#xff0c;…

繁花深處:花店建設的時代意義與多元應用—仙盟創夢IDE

花店當第一縷晨光透過花店的玻璃窗&#xff0c;落在帶著露水的玫瑰花瓣上時&#xff0c;這個空間便不再只是商品交易的場所。花店作為城市肌理中充滿生命力的細胞&#xff0c;承載著遠比銷售鮮花更豐富的社會意義。在快節奏的現代生活中&#xff0c;一束鮮花的綻放不僅是自然之…

AtomicStampedReference解決方案

1、通過引入版本戳(stamp)機制解決ABA問題&#xff1a; 每次修改時遞增版本號執行CAS時同時檢查值和版本號即使值相同但版本不同&#xff0c;操作也會失敗2、具體代碼實現 import java.util.concurrent.atomic.AtomicStampedReference;public class AtomicStampedReferenceDemo…

版本控制的詳細說明介紹(已有github賬號版)

說明 如果已經有一個GitHub賬號,這是一個很好的起點!版本控制是一個幫助你管理代碼或其他文件變化的工具,就像給你的項目加了一個“時間機器”,可以隨時回溯歷史、協作編輯,而不會亂套。下面我將從基礎開始,層層展開說明。整個內容分為幾個部分:介紹、原理、用途、操作…

基于Github Pages搭建個人博客站點:hexo環境搭建、本地預覽與發布

步驟確認 Hexo 博客的源文件在哪里安裝 Hexo 命令行工具&#xff1a;npm install -g hexo-cli在源文件目錄中使用 hexo new "文章標題" 創建新文章編輯生成的 Markdown 文件使用 hexo generate 生成靜態文件使用 hexo deploy 部署到這個 GitHub Pages 倉庫設置Hexo博…

Shell腳本實現自動封禁惡意掃描IP

iptables 簡介我們使用iptables工具實現功能iptables 是 Linux 系統上最常用的防火墻工具&#xff0c;可以指定策略。Shell文件創建首先我們先創建文件scanners.shvim /usr/local/bin/auto_block_ip.sh我的目標是每10分鐘自動掃描&#xff0c;再10分鐘內一個IP訪問50次以上就就…

LeetCode_哈希表

哈希表&#xff08;散列表&#xff09;一、哈希表二、有效的字母異位詞1、有效的字母異位詞(力扣242)2、贖金信(力扣383)3、字母異位詞分組(力扣49)4、找到字符串中所有字母異位詞(力扣438)三、兩個數組的交集1、兩個數組的交集(力扣349)2、兩個數組的交集 II(力扣350)三、其他…

2.變量和常量

1.變量2.2 變量的基本使用2.3 變量的本質 2.4 變量命名規則與規范 2.5 變量拓展-數組 1.數組的基本使用 2.常量

Java并發核心基礎解析

目錄 一、背景 二、Java線程模型 三、Synchronized實現原理 3.1 鎖的使用 3.2 解釋執行 3.3 JIT執行 3.4 鎖的狀態 3.5 monitorenter 3.5.1 偏向鎖 3.5.2 輕量級鎖 3.5.3 重量級鎖 3.6 monitorexit 3.6.1 偏向鎖 3.6.2 輕量級鎖 3.6.3 重量級 四、可見性的真相…