Linux TCP與Socket與IO多路復用(Epoll)

目錄

一、背景

二、交互流程

2.1 數據流動

2.2 對象之間的關系

三、TCP

3.1 為什么需要三次握手

3.2?三次握手流程

3.3 三次握手后的產物

3.4 TCB

四、Socket

4.1?Java Socket和C++ Socket

4.2 Socket的本質

4.3 Socket和TCB的關系

4.4 通過文件描述符調用Socket的流程

五、Epoll

5.1 Epoll 結構

5.2 Epoll簡要工作流程

5.3 Epoll代碼

5.4?epoll_ctl過程

5.5 epoll_wait過程

5.6?水平觸發(LT)與邊緣觸發(ET)

5.7 與Java NIO關系


一、背景

網絡傳輸無處不在,正確理解網絡傳輸的步驟有助于我們寫出高性能的程序,也有助于我們解決程序中出現的問題。

二、交互流程

下面的不理解可以跳過?二、交互流程

2.1 數據流動

網卡 → DMA緩沖區 → 協議棧處理(IP/TCP) → TCB接收緩沖區 → recv() → 用戶空間緩沖區
應用程序 → send() → 用戶空間緩沖區 → 內核發送緩沖區 → 協議棧處理 → 網卡隊列 → 網絡

2.2 對象之間的關系

epollfd?→?struct file?→?struct socket?→?struct sock(TCB 的核心數據結構)

三、TCP

老生常談的東西了,基本就是三次握手,但這次我會從操作系統角度,談談還干了什么,還包括三次握手的生成對象TCB

3.1 為什么需要三次握手

  • 第一次握手(SYN):服務端確認客戶端的發送能力正常。

  • 第二次握手(SYN-ACK):客戶端確認服務端的接收和發送能力正常。

  • 第三次握手(ACK):服務端確認客戶端的接收能力正常。

  • 只有三次握手后,雙方才能確保彼此能正常收發數據。

TCP三次握手發生在網絡協議的傳輸層

3.2?三次握手流程

  1. 客戶端發起連接

    • 用戶調用connect(),內核發送SYN報文(設置初始序列號ISN)。

    • 創建TCB(傳輸控制塊):內核為連接分配資源(如struct tcp_sock),初始化序列號(ISN)、窗口大小等參數,TCB狀態變為SYN_SENT

  2. 服務端響應

    • DMA寫入內存:網卡通過DMA直接將報文數據(包括TCP頭、IP頭、以太網幀等)寫入內核預分配的接收緩沖區(如sk_buff結構)。

    • 觸發軟中斷:隨后網卡觸發軟中斷(如Linux中的NET_RX_SOFTIRQ),通知內核有新的數據包需要處理。

    • 創建半連接
      內核協議棧解析SYN包,創建傳輸控制塊(TCB),初始化連接狀態(如序列號、窗口大小),并將連接狀態設為SYN_RCVD(半開連接)。

    • 加入半連接隊列(SYN Queue)
      該連接(TCB)被存入半連接隊列,等待客戶端確認。

    • 構造SYN-ACK包
      內核生成SYN-ACK響應(設置SYN和ACK標志,分配服務器初始序列號,確認號為客戶端的序列號+1)。

    • DMA發送數據
      報文通過內核協議棧封裝(TCP頭→IP頭→MAC頭),存入網卡發送緩沖區,網卡通過DMA讀取并發送。、

    • 啟動重傳定時器
      為防止丟包,內核啟動定時器(默認約1秒),若未收到客戶端的ACK,將重傳SYN-ACK

  3. 最終確認

    • 客戶端收到SYN-ACK后,狀態變為ESTABLISHED,發送ACK

    • 服務端收到ACK后,做3-6步驟的操作

    • DMA與軟中斷:客戶端的ACK包由網卡通過DMA寫入內存,再次觸發NET_RX_SOFTIRQ軟中斷。
    • 驗證ACK:內核檢查ACK的合法性(確認號是否為服務器序列號+1)。
    • 連接狀態遷移:若驗證通過,連接狀態轉為ESTABLISHED,并從半連接隊列移至全連接隊列(Accept Queue)。
    • 通知應用層:應用通過accept()系統調用從全連接隊列中獲取新連接,開始數據傳輸。

3.3 三次握手后的產物

主要是TCB和全連接隊列

全連接隊列:存放已建立連接但未被accept()取出的TCB

3.4 TCB

1. 存儲連接狀態信息

  • 連接狀態:記錄 TCP 狀態機的當前階段(如?ESTABLISHEDTIME_WAITSYN_RECEIVED?等)。

  • 端點信息:保存本地和遠端的 IP 地址及端口號,唯一標識一個 TCP 連接。

  • 序列號和確認號:維護發送和接收數據的序列號(SEQ)和確認號(ACK),保證數據有序性和可靠性。

2. 完成數據傳輸

  • 每個 TCP 連接由?四元組?唯一標識:
    <本地 IP, 本地端口, 遠端 IP, 遠端端口>
    只要四元組中任意一個元素不同,內核就會視為?不同的 TCP 連接,并為其分配獨立的 TCB(傳輸控制塊)。

    當應用程序通過socket fd執行read()/write()時,內核會通過關聯的TCB完成實際的數據傳輸

3. 緩沖區和數據管理

  • 發送緩沖區:暫存應用層待發送的數據,直到收到對方的確認。

  • 接收緩沖區:存儲已接收但尚未被應用層讀取的數據。

4. 流量控制與窗口管理

  • 滑動窗口:記錄接收方的可用緩沖區大小(窗口大小),控制發送速率以避免接收方溢出。

  • 發送和接收窗口:跟蹤當前允許發送的數據范圍和已確認的數據范圍。

5. 連接生命周期管理

  • 三次握手:跟蹤?SYNSYN-ACKACK?的交換過程,完成連接建立。

  • 四次揮手:管理?FIN?包的交換,確保連接正常關閉或終止。

????

四、Socket

4.1?Java Socket和C++ Socket

Java Socket 和 C++ Socket 在 Linux 上的本質是相同的,它們的底層實現均基于?Linux 內核提供的同一套 Socket 接口。無論是 Java 的?java.net.Socket?還是 C++ 的?sys/socket.h,最終都會通過系統調用(如?socket(),?bind(),?connect()?等)與內核交互。區別僅在于語言層面的封裝和 API 設計。

既然是一樣的,我們后面主要是在操作系統層級進行分析

4.2 Socket的本質

Socket是文件描述符的一種類型。文件描述符可以表示多種資源(文件、管道、Socket等),Socket是其中用于網絡通信的一種。

通過文件描述符操作Socket:Socket的讀寫、關閉等操作均可通過其關聯的文件描述符完成:

使用通用I/O函數:如?read()write()close()

使用Socket專用函數:如?send()recv()bind()connect()?等,這些函數需要文件描述符作為參數。

4.3 Socket和TCB的關系

一一對應關系

  • 每個 TCP Socket 對應一個 TCB

    • 當應用調用?socket()?創建一個 TCP Socket 后,內核會為這個 Socket 分配一個 TCB。

    • TCB 的生命周期與 Socket 綁定:Socket 被創建時 TCB 初始化,Socket 關閉時 TCB 釋放。

  • Socket 是 TCB 的“用戶態句柄”

    • 應用通過 Socket 文件描述符操作連接(如發送數據、接收數據、關閉連接),內核根據 Socket 找到對應的 TCB,修改其狀態或觸發協議行為(如重傳、流量控制)。

  • 發送數據

    • 應用通過?send()?寫入 Socket 的數據會暫存到 TCB 的發送緩沖區,TCP 協議根據 TCB 中的窗口和擁塞控制參數決定何時發送。

  • 接收數據

    • 內核將收到的數據存入 TCB 的接收緩沖區,應用通過?recv()?從 Socket 讀取時,數據從接收緩沖區復制到用戶空間。

每個 Socket 文件描述符(fd)在內核中關聯到一個?struct socket?結構,該結構指向對應的?struct sock(即 TCB 的核心數據結構)。
關系鏈
fd?→?struct file?→?struct socket?→?struct sock(含接收緩沖區)。

4.4 通過文件描述符調用Socket的流程

對象級調用流程:

用戶調用 read(sockfd, buf, len)↓
通過 sockfd 找到進程文件描述符表中的 struct file↓
struct file 的 f_op->read() 調用 Socket 的具體實現(如 sock_read())↓
內核通過 struct file 的 private_data 找到 struct socket↓
最終操作 struct sock 的接收緩沖區(sk_receive_queue)讀取數據

接收流程:

  1. 數據到達內核
    數據包經過網卡接收、協議棧解析(IP/TCP 層處理)后,最終存入對應 TCP 連接的?TCB 接收緩沖區。該緩沖區位于內核空間,由內核管理。

  2. 應用程序調用?recv()
    當應用程序調用?recv(fd, buf, len, flags)?時:

    • fd(文件描述符):關聯到特定的 Socket,而該 Socket 綁定到唯一的 TCB。

    • 內核操作
      內核從該 TCB 的接收緩沖區中,復制數據到用戶提供的緩沖區?buf(位于用戶空間)。

    • 數據移除
      被成功復制的數據會從 TCB 的接收緩沖區中移除,釋放空間,接收窗口(rwnd)隨之擴大。

  3. 返回結果

    • 若接收緩沖區中有數據,recv()?立即返回實際讀取的字節數。

    • 若接收緩沖區為空:

      • 阻塞模式:進程休眠,直到新數據到達或連接關閉。

      • 非阻塞模式:立即返回錯誤碼(如?EAGAIN?或?EWOULDBLOCK)。

Q:TCB接收緩沖區的作用是什么?

(1)數據暫存與排序

  • TCB 的接收緩沖區存儲已通過 TCP 協議驗證的、按序排列的數據。例如:

    • 若數據包亂序到達,內核會在緩沖區中等待缺失的序列號填補后,再通知應用層讀取。

    • 若數據重復(如重傳包),內核直接丟棄冗余數據。

(2)流量控制的基礎

  • 接收緩沖區的剩余空間決定了 TCP 的?接收窗口(rwnd。此窗口通過 ACK 報文通告給發送方,控制其發送速率。

  • 若緩沖區滿,rwnd=0,發送方暫停發送,避免數據被丟棄。

(3)內核與用戶空間的橋梁

  • 數據從內核的 TCB 接收緩沖區到用戶空間的?buf,必須通過?拷貝(如?copy_to_user())。
    (注:零拷貝技術如?splice()?或?sendfile()?可繞過此步驟,但常規?recv()?需要拷貝。)

發送流程:

1. 應用程序提交數據

  • send()/write()?系統調用
    應用程序將數據寫入用戶空間緩沖區,調用?send()?觸發系統調用。

  • 數據拷貝到內核
    數據從用戶空間拷貝到 TCB 的發送緩沖區(內核空間)。

2. 發送緩沖區管理

  • 分片與封裝
    內核根據 MSS 將數據分片,添加 TCP/IP 頭部,生成 TCP 段。

  • 發送窗口約束
    僅允許發送窗口內的數據(已發送未確認數據 + 可發送未發送數據 ≤ 發送窗口大小)。

3. 協議棧處理

  • 滑動窗口與序列號
    每個 TCP 段攜帶序列號(seq),接收方據此確認數據順序。

  • 重傳機制
    已發送但未確認的 TCP 段保留在發送緩沖區的重傳隊列中,超時(RTO)或收到重復 ACK 時觸發重傳。

4. 網絡層與網卡發送

  • IP 層處理
    添加 IP 頭部,路由選擇,分片(若超過 MTU)。

  • 網卡隊列
    TCP 段交給網卡驅動,存入發送隊列(如?tx_ring),通過 DMA 發送到網絡。

五、Epoll

經過上面的介紹,我們對文件描述符、Socket、TCP有相應的了解,也明白了文件描述符是如何操作網絡連接的。

那假如有大量的網絡連接時,我們該如何管理呢?

目前主流的方法是I/O 多路復用,即單線程/少量線程監聽多個socket事件

Epoll是Linux下的一種I/O多路復用機制,用于高效地處理大量文件描述符

5.1 Epoll 結構

epoll?的實現依賴于兩個核心數據結構:紅黑樹(Red-Black Tree)?和?就緒隊列(Ready List)。它們共同協作,使得?epoll?能夠高效地管理海量文件描述符(FD)的 I/O 事件。

紅黑樹是?epoll?實例中用于?存儲所有被監控的文件描述符(FD)?的數據結構。每個通過?epoll_ctl?添加的 FD(如套接字、管道等)都會在紅黑樹中注冊為一個節點。

設計原因

  • 高效動態操作:紅黑樹是一種自平衡二叉搜索樹,插入、刪除、查找的時間復雜度均為?O(log N),適合頻繁增刪 FD 的場景(例如 Web 服務器處理大量短連接)。

  • 快速定位 FD:當某個 FD 發生事件(如可讀、可寫)時,內核需要快速找到該 FD 的監控信息(例如用戶關注的事件類型),紅黑樹的特性確保了這一過程的效率。

  • 避免重復注冊:紅黑樹的唯一性保證同一個 FD 不會被重復添加,避免資源浪費。

就緒隊列是?epoll?實例中用于?臨時存儲已觸發事件的 FD?的鏈表結構。當某個被監控的 FD 發生事件(例如套接字收到數據),內核會將該 FD 添加到就緒隊列中。

設計原因

  • 快速事件通知:用戶調用?epoll_wait?時,內核無需遍歷所有被監控的 FD,而是直接檢查就緒隊列,時間復雜度接近?O(1)

  • 事件去重與合并:如果同一 FD 的多個事件連續觸發(如多次可讀),就緒隊列會合并這些事件,避免重復通知。

  • 支持邊緣觸發(Edge-Triggered, ET)模式:在 ET 模式下,事件僅在狀態變化時觸發一次,就緒隊列確保事件不會被遺漏。

工作流程

  1. 事件觸發:當某個 FD 發生事件(如數據到達),內核調用與該 FD 關聯的回調函數。

  2. 加入就緒隊列:回調函數將 FD 插入就緒隊列,并標記觸發的事件類型。

  3. 用戶獲取事件:用戶調用?epoll_wait?時,內核將就緒隊列中的事件拷貝到用戶空間,并清空隊列(取決于觸發模式)。

5.2 Epoll簡要工作流程

  1. 創建epoll實例

    • 使用?epoll_create1()?創建epoll文件描述符。

  2. 創建并配置監聽Socket

    • 創建TCP Socket,設置為非阻塞模式,綁定地址并開始監聽。

  3. 注冊監聽Socket到epoll

    • 通過?epoll_ctl()?將監聽Socket加入epoll監控,關注?EPOLLIN?事件(新連接事件)。

  4. 事件循環

    • 使用?epoll_wait()?阻塞等待事件發生。

    • 遍歷就緒事件列表,處理不同類型的事件:

      • 新連接:接受連接,將新Socket加入epoll監控。

      • 數據可讀:讀取數據并處理,必要時注冊?EPOLLOUT?事件準備寫入。

      • 數據可寫:發送數據,完成后取消?EPOLLOUT?監控。

      • 錯誤/關閉:移除并關閉Socket。

  5. 清理資源

    • 關閉所有Socket和epoll實例。

5.3 Epoll代碼

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <fcntl.h>#define MAX_EVENTS 10
#define PORT 8080
#define BUFFER_SIZE 1024// 設置文件描述符為非阻塞模式
void set_nonblocking(int fd) {int flags = fcntl(fd, F_GETFL, 0);fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}int main() {int listen_fd, epoll_fd, nfds;struct epoll_event ev, events[MAX_EVENTS];struct sockaddr_in addr;// 1. 創建監聽Socketlisten_fd = socket(AF_INET, SOCK_STREAM, 0);if (listen_fd == -1) {perror("socket");exit(EXIT_FAILURE);}// 綁定并監聽memset(&addr, 0, sizeof(addr));addr.sin_family = AF_INET;addr.sin_addr.s_addr = htonl(INADDR_ANY);addr.sin_port = htons(PORT);if (bind(listen_fd, (struct sockaddr*)&addr, sizeof(addr)) {perror("bind");close(listen_fd);exit(EXIT_FAILURE);}if (listen(listen_fd, SOMAXCONN)) {perror("listen");close(listen_fd);exit(EXIT_FAILURE);}set_nonblocking(listen_fd); // 非阻塞模式// 2. 創建epoll實例epoll_fd = epoll_create1(0);if (epoll_fd == -1) {perror("epoll_create1");close(listen_fd);exit(EXIT_FAILURE);}// 3. 注冊監聽Socket到epollev.events = EPOLLIN; // 關注可讀事件ev.data.fd = listen_fd;if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev)) {perror("epoll_ctl: listen_fd");close(listen_fd);exit(EXIT_FAILURE);}printf("Server listening on port %d...\n", PORT);// 4. 事件循環while (1) {nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);if (nfds == -1) {perror("epoll_wait");break;}for (int i = 0; i < nfds; i++) {int fd = events[i].data.fd;// 處理新連接if (fd == listen_fd) {struct sockaddr_in client_addr;socklen_t addrlen = sizeof(client_addr);int client_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &addrlen);if (client_fd == -1) {perror("accept");continue;}set_nonblocking(client_fd); // 新Socket設為非阻塞ev.events = EPOLLIN | EPOLLET; // 邊緣觸發模式(可選)ev.data.fd = client_fd;if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev) == -1) {perror("epoll_ctl: client_fd");close(client_fd);}printf("New connection: fd %d\n", client_fd);// 處理數據可讀} else if (events[i].events & EPOLLIN) {char buffer[BUFFER_SIZE];ssize_t nread = recv(fd, buffer, BUFFER_SIZE, 0);if (nread > 0) {printf("Received from fd %d: %.*s\n", fd, (int)nread, buffer);// 回顯數據(示例)send(fd, buffer, nread, 0);} else if (nread == 0 || (nread == -1 && errno != EAGAIN)) {// 關閉連接printf("Closing fd %d\n", fd);epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL);close(fd);}}// 處理其他事件(如EPOLLOUT、EPOLLERR等)}}// 清理資源close(listen_fd);close(epoll_fd);return 0;
}

5.4?epoll_ctl過程

當通過?epoll_ctl(EPOLL_CTL_ADD)?將一個fd(如Socket)添加到epoll實例時,內核會執行以下操作:

(1) 注冊回調函數到fd的等待隊列

  1. 為fd創建epoll條目(epitem:包含fd的信息和關注的事件(如EPOLLIN)。

  2. 將回調函數?ep_poll_callback?注冊到fd的等待隊列

    • 調用fd的?poll?方法(如Socket的?sock_poll)。

    • poll?方法將?ep_poll_callback?添加到fd的等待隊列中。

(2) 事件觸發時的回調流程

  1. 數據到達觸發硬件中斷:網卡接收數據后,內核協議棧處理數據并標記Socket為可讀。

  2. 喚醒等待隊列

    • 內核調用Socket等待隊列中的回調函數?ep_poll_callback

    • ep_poll_callback?將對應的fd(封裝為?epitem)加入epoll的就緒隊列(rdllist)。

  3. 通知用戶程序

    • 如果用戶程序阻塞在?epoll_wait,內核喚醒該線程,使其從?epoll_wait?返回并處理就緒事件。

5.5 epoll_wait過程

epoll_wait?是?epoll?機制的核心函數,它負責?等待并獲取已就緒的事件

步驟 1:進入內核態

  • 用戶程序調用?epoll_wait?時,會從用戶態切換到內核態。

  • 內核訪問?epoll?實例的數據結構(包括?紅黑樹?和?就緒隊列)。

步驟 2:檢查就緒隊列

  • epoll?實例維護一個?就緒隊列(ready list),其中保存所有已觸發事件的fd。

  • 如果就緒隊列非空,內核直接從中取出事件,填充到用戶空間的?events?數組。

  • 如果隊列為空,且?timeout=-1,線程阻塞在此處,直到有新事件到來或信號中斷。

步驟 3:監控fd狀態(若就緒隊列為空)

  • 若就緒隊列為空,內核通過?回調機制?監控所有注冊的fd:

    • 當某個fd發生事件(如socket接收數據),內核會將該fd添加到就緒隊列。

    • 這一過程由內核的?事件驅動機制?實現,無需輪詢所有fd,效率極高。

步驟 4:返回就緒事件

  • 將就緒隊列中的事件復制到用戶空間的?events?數組。

  • 返回就緒事件的數量?nfds,用戶程序通過遍歷?events[0..nfds-1]?處理事件。

  • 如果此時有線程阻塞在?epoll_wait,內核會喚醒該線程

5.6?水平觸發(LT)與邊緣觸發(ET)

行為水平觸發(LT)邊緣觸發(ET)
觸發時機只要緩沖區有數據/可寫,持續觸發僅在緩沖區狀態變化時觸發一次(如新數據到達)
數據未讀盡的后果下次?epoll_wait?繼續報告事件不再觸發事件,可能導致數據滯留
編程復雜度較低(無需一次性處理所有數據)較高(需循環讀寫至?EAGAIN
適用場景簡單場景、小數據量高性能場景、需精細化控制

5.7 與Java NIO關系

Java NIO 在不同的操作系統和 JDK 版本中確實會使用不同的底層實現,其中在?Linux 系統上,Java NIO 的?Selector(多路復用機制)默認是基于?epoll?實現的

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

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

相關文章

字節跳動旗下火山引擎都覆蓋哪些領域

首先&#xff0c;我需要確認火山引擎的主要業務范圍。根據之前的資料&#xff0c;火山引擎是字節跳動的企業技術服務平臺&#xff0c;可能包括云服務、人工智能、大數據分析等。不過需要更詳細的信息&#xff0c;比如具體的產品和服務&#xff0c;覆蓋的行業等。 接下來&#x…

如何配置jmeter做分布式壓測

問&#xff1a;為何需要做分布式 答&#xff1a;當我們本地機器jmeter進行壓測時&#xff0c;單臺JMeter機器通常無法穩定生成2000 QPS&#xff08;受限于CPU、內存、網絡帶寬&#xff09;&#xff0c;本地端口耗盡&#xff1a;操作系統可用的臨時端口&#xff08;Ephemeral P…

【算法提升】牛牛沖鉆五 最長無重復子數組 重排字符串 one_day

算法提升 1.牛牛沖鉆五1.2 解析 2.最長無重復子數組2.1解析 3.重排字符串3.1解析 1.牛牛沖鉆五 1.2 解析 后面的數據要根據前面兩個的狀態來確定&#xff0c;我的做法是使用動態規劃的方式 #include<iostream> #include<string> #include<vector> using n…

數學建模MathAI智能體-2025電工杯A題實戰

題目&#xff1a; 光伏電站發電功率日前預測問題 光伏發電是通過半導體材料的光電效應&#xff0c;將太陽能直接轉化為電能的技術。光伏電站是由眾多光伏發電單元組成的規模化發電設施。 光伏電站的發電功率主要由光伏板表面接收到的太陽輻射總量決定&#xff0c;不同季節太陽…

VR 展廳開啟一場穿越時空的邂逅?

在文化藝術領域&#xff0c;VR 展廳宛如一扇通往奇妙世界的大門&#xff0c;讓觀眾得以突破時間與空間的枷鎖&#xff0c;以一種前所未有的沉浸式體驗&#xff0c;與歷史文化和藝術作品展開親密無間的互動。博物館&#xff0c;作為承載著厚重歷史文化的璀璨寶庫&#xff0c;長久…

linux中使用make clean重新編譯

是的&#xff0c;在編譯完成后&#xff0c;你可以通過以下方式清除之前的編譯結果并重新編譯&#xff1a; 方法 1&#xff1a;直接刪除 build 目錄&#xff08;推薦&#xff09; 這是最徹底的清理方式&#xff0c;適用于需要完全重新配置或解決構建問題的情況。 # 進入項目根…

【Linux】的火墻管理及優化

目錄 iptables與firewalld服務 iptables的三表五鏈 iptables的安裝和啟用 iptables命令的格式及常用參數 命令格式 常用參數 編寫規則示例 firewalld的域 firewalld的啟用 firewalld-cmd命令的常用參數 firewalld的高級規則 firewalld的地址偽裝與端口轉發 iptable…

古文時空重構:當AI把課本詩詞做成4D電影

當青銅編鐘聲由遠及近&#xff0c;AI生成的水墨粒子逐漸凝聚成標題 當苔痕在石階上悄然蔓延時&#xff0c;你聽見劉禹錫筆下的呼吸了嗎&#xff1f; 當鏡頭突然穿透墨跡&#xff0c;3D古卷如星河鋪展&#xff01; 當AI把課本詩詞做成4D電影&#xff0c;這樣的視頻流量會不會高…

自動生成圖標小程序(iOS)

續上篇《iOS應用程序開發(圖片處理器&#xff09;》 這是一個圖片瀏覽器和處理器&#xff0c;增加一些功能&#xff0c;可以自動生成小圖標。 (This is a picture viewer and editor.You can add some functions,generate the icon automatically.You can select the object …

Netty應用:從零搭建Java游戲服務器網絡框架

在游戲開發領域,服務器網絡框架是連接玩家與游戲世界的橋梁,其穩定性和高效性直接影響玩家的游戲體驗。本文將詳細介紹如何使用Java語言和Netty框架,搭建一個兼具TCP和UDP協議支持的游戲服務器網絡框架,并配套開發客戶端,助你快速掌握游戲網絡開發的核心技術。 1.項目概覽…

SpringBoot-13-多表查詢之一對一查詢association

文章目錄 1 mysql數據庫1.1 account賬戶表1.2 user用戶表2 實體類2.1 model/Account.java2.2 model/User.java3 mapper3.1 AccountToUserMapper.java3.2 AccountToUserMapper.xml3.2.1 mapper3.2.2 resultMap3.2.3 association3.2.4 select4 AccountController.java5 測試5.1 有…

Python如何賦能自動駕駛地圖構建?從點云處理到實時導航

Python如何賦能自動駕駛地圖構建?從點云處理到實時導航 自動駕駛的核心是什么?毫無疑問,精準的地圖 是整個系統的靈魂。沒有高精度地圖,自動駕駛汽車就如同在迷霧中航行。而 Python,憑借其強大的數據處理能力和豐富的開源生態,正在成為自動駕駛地圖構建的關鍵工具。 今…

QT之巧用對象充當信號接收者

備注&#xff1a;以下僅為演示不代表合理性&#xff0c;適合簡單任務&#xff0c;邏輯簡單、臨時使用&#xff0c;可保持代碼簡潔&#xff0c;對于復雜的任務應創建一個專門的類來管理信號和線程池任務. FileScanner類繼承QObject和QRunnable&#xff0c;掃描指定目錄下的文件獲…

Transformer,多頭注意力機制 隱式學習子空間劃分

Transformer,多頭注意力機制 隱式學習子空間劃分 在Transformer中,多頭注意力機制天然支持隱式學習子空間劃分——每個注意力頭可以專注于輸入的不同方面(如語義、句法、位置關系等),從而隱式形成多個子空間。 一、核心思路:將多頭注意力視為隱式子空間 原理 Transfo…

java基礎(繼承)

什么是繼承 繼承好處 提高代碼的復用性 繼承注意事項 權限修飾符 單繼承、Object類 沖突&#xff1a; 方法重寫 擴展&#xff1a; 其實我們不想看地址&#xff0c;地址看來沒用&#xff0c;我們是用來看對象有沒有問題 重寫toString: 比如這個如果返回的是地址值&#xff0c;…

【每日渲美學】3ds Max櫥柜材質教程:廚房高光烤漆、木紋、亞克力、亞光板材渲染優化指南

在室內可視化項目中&#xff0c;廚房往往是一個集中展現材質表現力與光影質感的關鍵區域。櫥柜作為廚房空間的視覺主體&#xff0c;其材質選擇與渲染設置不僅影響整體空間的風格呈現&#xff0c;也對渲染效率提出更高要求。 本期「每日渲美學」&#xff0c;我們聚焦3ds Max環境…

Python Day34

Task&#xff1a; GPU訓練及類的call方法 1.CPU性能的查看&#xff1a;看架構代際、核心數、線程數 2.GPU性能的查看&#xff1a;看顯存、看級別、看架構代際 3.GPU訓練的方法&#xff1a;數據和模型移動到GPU device上 4.類的call方法&#xff1a;為什么定義前向傳播時可以直接…

HTTP協議版本的發展(HTTP/0.9、1.0、1.1、2、3)

目錄 HTTP協議層次圖 HTTP/0.9 例子 HTTP/1.0 Content-Type 字段 Content-Encoding 字段 例子 1.0版本存在的問題&#xff1a;短鏈接、隊頭阻塞 HTTP/1.1 Host字段 Content-Length 字段 分塊傳輸編碼 1.1版本存在的問題 HTTP/2 HTTP/2數據傳輸 2版本存在的問題…

開源 OIDC(OpenID Connect)身份提供方(IdP)、iam選型

文章目錄 開源 OIDC(OpenID Connect)身份提供方(IdP)、iam選型主流開源 OIDC(OpenID Connect)身份提供方(IdP)zitadeldexory開源 OIDC(OpenID Connect)身份提供方(IdP)、iam選型 主流開源 OIDC(OpenID Connect)身份提供方(IdP) 當前主流的**開源 OIDC(OpenI…

第三十二天打卡

作業&#xff1a;參考pdpbox官方文檔中的其他類&#xff0c;繪制相應的圖&#xff0c;任選即可 1. 安裝并導入庫 確保安裝與文檔版本一致的 pdpbox&#xff08;此處以 0.3.0 為例&#xff09;&#xff1a; bash 復制 下載 pip install pdpbox0.3.0 導入所需庫&#xff1a…