SO_REUSEPORT 之 TCP負載均衡驗證

首先啟動兩個tcp server, 代碼里開啟 SO_REUSEPORT
?

[my_test@localhost test]$ ./tcp_server_reuseport &
[1] 1864
[my_test@localhost test]$ Server listening on port 8888[my_test@localhost test]$ ./tcp_server_reuseport &
[2] 1865
[my_test@localhost test]$ Server listening on port 8888[my_test@localhost test]$ ps -ef|grep tcp_server_reuseport
my_test         1864    1443  0 23:11 pts/0    00:00:00 ./tcp_server_reuseport
my_test         1865    1443  0 23:11 pts/0    00:00:00 ./tcp_server_reuseport

啟動10條客戶端連接:

[my_test@localhost test]$ ./tcp_client_reuseport
Message sent
Server response: Welcome to the server! Server PID: 1865Message sent
Server response: Welcome to the server! Server PID: 1864Message sent
Server response: Welcome to the server! Server PID: 1865Message sent
Server response: Welcome to the server! Server PID: 1864Message sent
Server response: Welcome to the server! Server PID: 1864Message sent
Server response: Welcome to the server! Server PID: 1865Message sent
Server response: Welcome to the server! Server PID: 1865Message sent
Server response: Welcome to the server! Server PID: 1865Message sent
Server response: Welcome to the server! Server PID: 1864Message sent
Server response: Welcome to the server! Server PID: 1864

從回復的server 進程id 可見,負載均衡做的很好。

追蹤內核調用鏈(內核版本5.10.216? x86_64):

在server端收到client的SYN連接請求時會觸發 __inet_lookup_listener -> inet_lhash2_lookup -> lookup_reuseport -> reuseport_select_sock 通過哈希選擇一個Listen Socket來處理這個連接請求。

(gdb) b reuseport_select_sock
Breakpoint 1 at 0xffffffff8199ac80: file net/core/sock_reuseport.c, line 277.
(gdb) c
Continuing.
[New Thread 2061]
[Switching to Thread 2061]Thread 293 hit Breakpoint 1, reuseport_select_sock (sk=sk@entry=0xffff888038c90000, hash=317205834, skb=skb@entry=0xffff88800a90dce0,hdr_len=hdr_len@entry=40) at net/core/sock_reuseport.c:277
277     net/core/sock_reuseport.c: No such file or directory.
(gdb) bt
#0  reuseport_select_sock (sk=sk@entry=0xffff888038c90000, hash=317205834, skb=skb@entry=0xffff88800a90dce0, hdr_len=hdr_len@entry=40)at net/core/sock_reuseport.c:277
#1  0xffffffff81a03ff8 in lookup_reuseport (hnum=8888, daddr=0, sport=21715, saddr=251789322, doff=40, skb=0xffff88800a90dce0,sk=0xffff888038c90000, net=0xffffffff82a1ac40 <init_net>) at net/ipv4/inet_hashtables.c:265
#2  lookup_reuseport (hnum=8888, daddr=0, sport=21715, saddr=251789322, doff=40, skb=0xffff88800a90dce0, sk=0xffff888038c90000,net=0xffffffff82a1ac40 <init_net>) at net/ipv4/inet_hashtables.c:255
#3  inet_lhash2_lookup (net=net@entry=0xffffffff82a1ac40 <init_net>, ilb2=<optimized out>, skb=skb@entry=0xffff88800a90dce0,doff=doff@entry=40, saddr=saddr@entry=251789322, sport=sport@entry=21715, daddr=0, hnum=8888, dif=2, sdif=0)at net/ipv4/inet_hashtables.c:293
#4  0xffffffff81a042f3 in __inet_lookup_listener (net=net@entry=0xffffffff82a1ac40 <init_net>,hashinfo=hashinfo@entry=0xffffffff832a69c0 <tcp_hashinfo>, skb=skb@entry=0xffff88800a90dce0, doff=doff@entry=40,saddr=saddr@entry=251789322, sport=sport@entry=21715, daddr=<optimized out>, hnum=8888, dif=2, sdif=0)at net/ipv4/inet_hashtables.c:361
#5  0xffffffff81a25978 in __inet_lookup (hashinfo=0xffffffff832a69c0 <tcp_hashinfo>, sdif=0, refcounted=<synthetic pointer>, dif=2,dport=<optimized out>, daddr=251789322, sport=<optimized out>, saddr=251789322, doff=<optimized out>, skb=0xffff88800a90dce0,net=0xffffffff82a1ac40 <init_net>) at ./include/net/inet_hashtables.h:343
#6  __inet_lookup_skb (hashinfo=0xffffffff832a69c0 <tcp_hashinfo>, sdif=0, refcounted=<synthetic pointer>, dport=<optimized out>,sport=<optimized out>, doff=<optimized out>, skb=0xffff88800a90dce0) at ./include/net/inet_hashtables.h:379
#7  tcp_v4_rcv (skb=0xffff88800a90dce0) at net/ipv4/tcp_ipv4.c:1984
#8  0xffffffff819f922b in ip_protocol_deliver_rcu (net=0xffffffff82a1ac40 <init_net>, skb=0xffff88800a90dce0,protocol=<optimized out>) at net/ipv4/ip_input.c:204
#9  0xffffffff819f93ef in ip_local_deliver_finish (net=<optimized out>, sk=<optimized out>, skb=<optimized out>)at ./include/linux/skbuff.h:2533
#10 0xffffffff819f94fa in NF_HOOK (sk=0x0 <fixed_percpu_data>, pf=2 '\002', hook=1, in=<optimized out>, out=0x0 <fixed_percpu_data>,okfn=0xffffffff819f93b0 <ip_local_deliver_finish>, skb=0xffff88800a90dce0, net=0xffffffff82a1ac40 <init_net>)at ./include/linux/netfilter.h:296
#11 NF_HOOK (pf=2 '\002', sk=0x0 <fixed_percpu_data>, out=0x0 <fixed_percpu_data>, okfn=0xffffffff819f93b0 <ip_local_deliver_finish>,in=<optimized out>, skb=0xffff88800a90dce0, net=0xffffffff82a1ac40 <init_net>, hook=1) at ./include/linux/netfilter.h:290
#12 ip_local_deliver (skb=0xffff88800a90dce0) at net/ipv4/ip_input.c:252
#13 0xffffffff819f95e3 in NF_HOOK (sk=0x0 <fixed_percpu_data>, pf=2 '\002', hook=0, in=0xffff88800391b000,out=0x0 <fixed_percpu_data>, okfn=0xffffffff819f8c40 <ip_rcv_finish>, skb=0xffff88800a90dce0, net=0xffffffff82a1ac40 <init_net>)at ./include/linux/netfilter.h:296
#14 NF_HOOK (pf=2 '\002', sk=0x0 <fixed_percpu_data>, out=0x0 <fixed_percpu_data>, okfn=0xffffffff819f8c40 <ip_rcv_finish>,
--Type <RET> for more, q to quit, c to continue without paging--in=0xffff88800391b000, skb=0xffff88800a90dce0, net=0xffffffff82a1ac40 <init_net>, hook=0) at ./include/linux/netfilter.h:290
#15 ip_rcv (skb=0xffff88800a90dce0, dev=0xffff88800391b000, pt=<optimized out>, orig_dev=<optimized out>) at net/ipv4/ip_input.c:551
#16 0xffffffff819714a4 in __netif_receive_skb_one_core (skb=<optimized out>, pfmemalloc=<optimized out>) at net/core/dev.c:5375
#17 0xffffffff819716e9 in process_backlog (napi=0xffff88807dc2e3d0, quota=64) at net/core/dev.c:6396
#18 0xffffffff81972fce in napi_poll (repoll=0xffffc90000003f60, n=0xffff88807dc2e3d0) at net/core/dev.c:6847
#19 net_rx_action (h=<optimized out>) at net/core/dev.c:6917
#20 0xffffffff820000b7 in __do_softirq () at kernel/softirq.c:298
#21 0xffffffff81e0106f in asm_call_on_stack () at arch/x86/entry/entry_64.S:801
#22 0xffffffff81022372 in __run_on_irqstack (func=<optimized out>) at ./arch/x86/include/asm/irq_stack.h:26
#23 run_on_irqstack_cond (regs=0x0 <fixed_percpu_data>, func=<optimized out>) at ./arch/x86/include/asm/irq_stack.h:77
#24 do_softirq_own_stack () at arch/x86/kernel/irq_64.c:77
#25 0xffffffff8106c7aa in do_softirq () at kernel/softirq.c:343
#26 0xffffffff8106c7fa in do_softirq () at ./arch/x86/include/asm/preempt.h:26
#27 __local_bh_enable_ip (ip=ip@entry=18446744071589316362, cnt=cnt@entry=512) at kernel/softirq.c:195
#28 0xffffffff819fc71b in local_bh_enable () at ./include/linux/bottom_half.h:32
#29 rcu_read_unlock_bh () at ./include/linux/rcupdate.h:806
#30 ip_finish_output2 (net=<optimized out>, sk=<optimized out>, skb=<optimized out>) at net/ipv4/ip_output.c:238
#31 0xffffffff819feee8 in ip_finish_output (skb=0xffff88800a90dce0, sk=0xffff888038c92bc0, net=0xffffffff82a1ac40 <init_net>)at net/ipv4/ip_output.c:325
#32 NF_HOOK_COND (pf=2 '\002', hook=4, okfn=0xffffffff819fd670 <ip_finish_output>, cond=<optimized out>, out=<optimized out>,in=<optimized out>, skb=0xffff88800a90dce0, sk=0xffff888038c92bc0, net=0xffffffff82a1ac40 <init_net>)at ./include/linux/netfilter.h:285
#33 ip_output (net=0xffffffff82a1ac40 <init_net>, sk=0xffff888038c92bc0, skb=0xffff88800a90dce0) at net/ipv4/ip_output.c:439
#34 0xffffffff819fe982 in __ip_queue_xmit (sk=0xffff888038c92bc0, skb=0xffff88800a90dce0, fl=0xffff888038c92f20, tos=<optimized out>)at net/ipv4/ip_output.c:540
#35 0xffffffff819febbc in ip_queue_xmit (sk=<optimized out>, skb=<optimized out>, fl=<optimized out>) at ./include/net/inet_sock.h:302
#36 0xffffffff81a1bef6 in __tcp_transmit_skb (sk=sk@entry=0xffff888038c92bc0, skb=0xffff88800a90dce0, skb@entry=0xffff88800a90dc00,clone_it=clone_it@entry=1, gfp_mask=<optimized out>, rcv_nxt=<optimized out>) at net/ipv4/tcp_output.c:1407
#37 0xffffffff81a1c8ed in tcp_transmit_skb (gfp_mask=<optimized out>, clone_it=1, skb=0xffff88800a90dc00, sk=0xffff888038c92bc0)at ./include/linux/tcp.h:439
#38 tcp_connect (sk=sk@entry=0xffff888038c92bc0) at net/ipv4/tcp_output.c:3888
#39 0xffffffff81a22c90 in tcp_v4_connect (sk=0xffff888038c92bc0, uaddr=0xffffc90000d43e88, addr_len=<optimized out>)at net/ipv4/tcp_ipv4.c:314
--Type <RET> for more, q to quit, c to continue without paging--
#40 0xffffffff81a3d87c in __inet_stream_connect (sock=sock@entry=0xffff88803652f000, uaddr=0x12e82d4a,uaddr@entry=0xffffc90000d43e88, addr_len=177265888, addr_len@entry=16, flags=40, flags@entry=2, is_sendmsg=21715,is_sendmsg@entry=0) at net/ipv4/af_inet.c:666
#41 0xffffffff81a3db41 in inet_stream_connect (sock=0xffff88803652f000, uaddr=0xffffc90000d43e88, addr_len=16, flags=2)at net/ipv4/af_inet.c:730
#42 0xffffffff8194bdc5 in __sys_connect (fd=<optimized out>, uservaddr=0x7ffe8421f910, addrlen=16) at net/socket.c:1882
#43 0xffffffff8194be01 in __do_sys_connect (addrlen=<optimized out>, uservaddr=<optimized out>, fd=<optimized out>)at net/socket.c:1892
#44 __se_sys_connect (addrlen=<optimized out>, uservaddr=<optimized out>, fd=<optimized out>) at net/socket.c:1889
#45 __x64_sys_connect (regs=<optimized out>) at net/socket.c:1889
#46 0xffffffff81c38090 in do_syscall_64 (nr=<optimized out>, regs=0xffffc90000d43f58) at arch/x86/entry/common.c:46
#47 0xffffffff81e0011f in entry_SYSCALL_64 () at arch/x86/entry/entry_64.S:125
#48 0x0000000000000000 in ?? ()

具體代碼如下:

?server端演示代碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>#define PORT 8888
#define MAX_PENDING_CONNECTIONS 10int main() {int server_fd, new_socket;struct sockaddr_in address;int opt = 1;int addrlen = sizeof(address);// 創建套接字if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {perror("socket failed");exit(EXIT_FAILURE);}// 設置套接字選項if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt))) {perror("setsockopt");exit(EXIT_FAILURE);}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");exit(EXIT_FAILURE);}// 開始監聽連接if (listen(server_fd, MAX_PENDING_CONNECTIONS) < 0) {perror("listen");exit(EXIT_FAILURE);}printf("Server listening on port %d\n", PORT);while(1) {// 接受新連接if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) {perror("accept");exit(EXIT_FAILURE);}printf("New connection from %s:%d\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));// 向客戶端發送消息,包含當前進程IDchar welcome_message[100];int pid = getpid(); // 獲取當前進程的 IDsprintf(welcome_message, "Welcome to the server! Server PID: %d\n", pid);send(new_socket, welcome_message, strlen(welcome_message), 0);// 關閉與客戶端的連接close(new_socket);}return 0;
}

客戶端演示代碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define PORT 8888
#define SERVER_IP "10.0.2.15" // 服務器 IP 地址
#define MESSAGE "Hello from client"int main() {int sock = 0;struct sockaddr_in serv_addr;char message[1024] = {0};char buffer[1024] = {0};int i = 0;while (i++ < 10) {// 創建套接字if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {perror("socket creation error");exit(EXIT_FAILURE);}serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(PORT);if(inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr) <= 0) {perror("invalid address / address not supported");exit(EXIT_FAILURE);}// 連接到服務器if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {perror("connection failed");exit(EXIT_FAILURE);}// 向服務器發送消息send(sock, MESSAGE, strlen(MESSAGE), 0);printf("Message sent\n");// 接收服務器的響應if (recv(sock, buffer, sizeof(buffer), 0) < 0) {perror("recv failed");exit(EXIT_FAILURE);}printf("Server response: %s\n", buffer);// 關閉套接字close(sock);}return 0;
}

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

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

相關文章

網絡工程師備考1——基礎學習

認識設備 1 交換機 一、什么是交換機&#xff1f; 實現不同電腦之間數據的轉發 換機是一種用于電(光)信號轉發的網絡設備。 它可以為接入交換機的任意兩個網絡節點提供獨享的電信號通路。最常見的交換機是以太網交換機。交換機工作于OSI參考模型的第二層&#xff0c;即數據…

使用 Supabase 的 Realtime + Storage 非常方便呢

文章目錄 &#xff08;一&#xff09;Supabase&#xff08;二&#xff09;Realtime&#xff08;消息&#xff09;&#xff08;2.1&#xff09;Python 消息訂閱&#xff08;2.2&#xff09;JavaScript 消息訂閱 &#xff08;三&#xff09;Storage&#xff08;存儲&#xff09;&…

Linux:Ubuntu修改root密碼

Linux&#xff1a;Ubuntu修改root密碼 修改默認grub配置文件 rootshanxin:~# vim /etc/default/grub# 主要修改內容如下&#xff1a;GRUB_DEFAULT0 #GRUB_TIMEOUT_STYLEhidden 注釋這一行 GRUB_TIMEOUT5 # 將這一行的時間改為5秒進行開啟啟動的grub文件的復寫 rootshanxin:~…

芯課堂 | UI Creator 物理鍵盤移植指南

LVGL提供輸入設備的種類一共有5種&#xff0c;分別是&#xff1a;touchpad&#xff08;觸摸板&#xff09;、mouse&#xff08;鼠標&#xff09;、keypad&#xff08;鍵盤&#xff09;、encoder&#xff08;編碼器&#xff09;、button&#xff08;外部按鍵&#xff09;。而基于…

Tron 節點 性能壓測

文章目錄 一、代碼說明1.1 主要功能1.2 代碼示例1.3 代碼解釋1.4 執行流程 二、結果分析三、參數解釋3.1 numWorkers 和 numRequests 說明3.2 使用場景 四、注意事項 最近搭建了一個TRON節點&#xff0c;同事不相信我的自建節點比官方更靠譜&#xff0c;咱們給他使用golang寫一…

如何成為一個專業的AI產品經理?

可以找專業的老師帶。 可以找專業的內容學。 可以多遇挫折并快速學習&#xff0c;屢敗屢戰&#xff0c;筆者本人從業AI十年有余&#xff0c;吃了不少苦&#xff0c;有過很多或成功或失敗的經歷。 成為一個專業的AI產品經理需要一系列專業知識和技能的積累&#xff0c;以及在…

axios - 簡 單 的 請 求 模 板

import {message } from ant-design-vue import axios from axios import {useUserStore } from @/store/modules/user import router from @/routerconst instance = axios.create({baseURL: http://192.168.110.171:5201,timeout: 5000, })* 請求攔截器 insta

切換Ubuntu開機的主題

要將Ubuntu系統的啟動畫面&#xff08;即開機時的顯示界面&#xff09;從Lubuntu切換回原生的Ubuntu界面&#xff0c;可以按照以下步驟操作&#xff1a; 1. 安裝原生Ubuntu的plymouth主題 首先&#xff0c;確保你已經安裝了原生Ubuntu的plymouth主題。打開終端并運行以下命令…

基于Matlab卷積神經網絡(CNN)人臉識別系統

歡迎大家點贊、收藏、關注、評論啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代碼。 文章目錄 一項目簡介 二、功能三、系統四. 總結 一項目簡介 一、項目背景與意義 人臉識別技術作為計算機視覺領域的一個重要分支&#xff0c;已經廣泛應用于安全監控、身份驗證…

Python基礎知識歸納總結

目錄 一、線性表 總結 二、棧 三、隊列 四、哈希表 五、字符串 六、正則表達式 綜合示例 一、線性表 線性表&#xff08;通常用列表表示&#xff09;是一種按線性順序存儲元素的數據結構。 插入元素 (append, insert) 刪除元素 (remove, pop) 查找元素 (index) 更新…

FreeRTOS學習——FreeRTOS隊列(下)之隊列創建

本篇文章記錄我學習FreeRTOS隊列創建的知識。主要分享隊列創建需要使用的初始化函數、隊列復位函數。 需要進一步了解FreeRTOS隊列的相關知識&#xff0c;讀者可以參考以下文章&#xff1a; FreeRTOS學習——FreeRTOS隊列&#xff08;上&#xff09;_freertos 單元素隊列-CSDN博…

Spring、SpringMVC、SpringBoot 三者之間是什么關系

Spring、SpringMVC、SpringBoot 是三個獨立的框架&#xff0c;它們之間的關系是: 1. Spring是一個Java的輕量級應用框架&#xff0c;提供了基于IoC和AOP的支持&#xff0c;用于構建企業級應用。Spring有多 個模塊&#xff0c;包括 Spring Core、Spring Context、Spring JDBC、…

高質量油封選擇的重要性

在現代工業和機械系統中&#xff0c;油封的作用至關重要。它們不僅防止潤滑劑泄漏&#xff0c;還阻止污染物進入系統&#xff0c;從而保障設備的正常運行。選擇高質量的油封對于保證設備性能、延長使用壽命和降低維護成本至關重要。本文將從多個角度探討選擇高質量油封的重要性…

【hackmyvm】Slowman靶機

文章目錄 主機探測端口探測FTP匿名登錄 目錄探測hydra爆破mysql爆破zip------fcrackzip爆破密碼-----john提權 主機探測 ┌──(root?kali)-[/home/kali] └─# fping -ag 192.168.9.1/24 2>/dev/null 192.168.9.221 主機192.168.9.224 靶機端口探測 ┌──(roo…

送變電乙級資質申請攻略:關鍵步驟與注意事項

關鍵步驟&#xff1a; 工商注冊與資本核實&#xff1a; 確保企業已正式注冊&#xff0c;且注冊資金不少于100萬元人民幣&#xff0c;同時準備企業法人營業執照等相關證明文件。 人員配置與注冊&#xff1a; 根據資質要求&#xff0c;配置齊全合理的專業技術人員&#xff0c;包括…

【教程】Linux 安裝 kkFileView 文檔在線預覽項目 及優化

【教程】Linux 安裝 kkFileView 文檔在線預覽項目 官網 kkFileView - 在線文件預覽 (keking.cn) 安裝包 可以直接下載成品 也可以下載source 源碼 自己編譯 kkFileView 發行版 - Gitee.com 打開IDEA 然后先clear 再install 然后在 file-online-preview\server\target 目錄…

Nginx R31 doc-09-Serving Static Content 靜態內容

提供靜態內容 配置 NGINX 和 NGINX Plus 以提供靜態內容&#xff0c;使用類型特定的根目錄&#xff0c;檢查文件存在性&#xff0c;并進行性能優化。 本節介紹如何配置 NGINX 和 NGINX Plus 以提供靜態內容&#xff0c;如何定義搜索請求文件的路徑&#xff0c;如何設置索引文…

WordPress插件Disable WP REST API,可根據是否登錄來禁用REST API

前面跟大家分享了代碼版禁用WordPress REST API的方法&#xff08;詳見『WordPress4.7以上版本如何禁用JSON REST API&#xff1f;』&#xff09;&#xff0c;不過有些站長不太敢折騰自己的網站代碼&#xff0c;那么建議試試這款Disable WP REST API&#xff0c;它可以&#xf…

小結5:朗讀練習第二段

五、朗讀練習2 2024-5-6始&#xff0c;5-14終&#xff0c;5-15寫。 我漸漸體會到一些朗讀的樂趣。但我還要考研&#xff0c;要寫作業、期末考試。如果是在大一該多好。我可以就這樣一天一天的寫下去&#xff0c;慢慢地有一些自己的作品&#xff0c;還能錄視頻發到b站上。 上一篇…

通過修改物理內存實現跨進程內存讀寫

習一下利用修改物理內存來跨進程內存讀寫 系統&#xff1a;win10 21h1 x64 編譯環境: vs2022 詳情見附錄 基礎 虛擬地址轉物理地址 虛擬地址也稱線性地址&#xff0c;一個線性地址進程的DirBase地址可以轉換成物理地址。先來看線性地址的含義 在x64體系中只實現了48位的virtu…