?嵌入式Linux學習 - 網絡服務器實現與客戶端的通信

1.單循環服務器

2.并發服務器

1. 設置socket屬性

2. 進程

?3. 線程

3.多路IO復用模型 - 提高并發程度

1. 區別

2. IO處理模型

1. 阻塞IO模型

2. 非阻塞IO模型

3. 信號驅動IO

4. IO多路復用

3. 特點

4. 函數接口

1. select

2. poll

3. epoll

半包


1.單循環服務器

?

2.并發服務器

1. 設置socket屬性

原型:int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen)
功能:
在bind前 設置socket的屬性
參數:
????????sockfd????????要設置的socket
????????level???????????設置socket層次//socket本身 tcp ip
????????optname????選項名字
????????optval????????選項值
????????optlen????????長度
設置一個選項(開啟一個功能))---讓地址重用,即可停止后立即使用
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int));

2. 進程:

ps aux | grep ser????????查找包含ser的進程


signal(SIGCHILD, do_child)???????

父進程接收子進程結束信號exit(0)后回收子進程資源,防止僵尸態


void do_child(int signo)
{????????wait(NULL);}

?
3. 線程:

退出個體線程使用pthread_exit(NULL)
pthread_join()會阻塞程序,無法接收多個客戶端信息,所以選擇pthread_detach()回收資源

3.多路IO復用模型 - 提高并發程度

1. 區別

多進程和多線程:一個客戶端對應一個進程或線程
IO多路復用???????:多個客戶端對應一個進程或線程

2. IO處理模型

1. 阻塞IO模型:

特點:簡單,低效

i - 讀:scanf, getchar,read,recv
? ? ? ? ? ? 操作:從終端stdin讀取數據 =>?阻塞等待讀取數據 =>?返回用戶空間

o- 寫:pipe(一直向管道寫入數據,管道內存滿時阻塞)

2. 非阻塞IO模型

特點:輪詢,CPU負擔重

操作:從終端stdin讀取數據 => 不等待讀取數據 => 直接返回用戶空間
? ? ? ? ? ?O_NONBLOCK 打開文件時可以設置為非阻塞模式

3. 信號驅動IO

設置非阻塞:fcntl,并與信號結合

特點:處理多路IO時資源數量有限

  • 原型:int fcntl(int fd, int cmd, ...)
  • 功能:

維護文件描述符

  • 參數

????????fd??????????????????要操作的fd
????????cmd??????????????要做的操作

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? F_GETFL? ? ? ? ? ? ? ? ? ?開啟異步信號

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? F_SETFL? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? F_SETOWN? ? ? ? ? ? ? 設置與信號的關聯

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????????? fcntl(fd, F_SETOWN, gtpid());
????????...??????????????????可變參數? ? ? ? ? ? ? ? ? ? ? ? ? ? ?eg:printf(const char *format,...);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf("hello");????????printf("a = %d\n", a);

  • 返回值

成功時返回值取決于所作的操作

與信號的結合:signo

4. IO多路復用

3. 特點

1. 可以處理多路IO

2. 不需要阻塞

3. 不需要輪詢

4. 函數接口

1. select

  • 原型:int select(int nfds,
    ????????????????????????fd_set *readfds,
    ????????????????????????fd_set *writefds,
    ????????????????????????fd_set *exceptfds,
    ????????????????????????struct timeval *timeout);
  • 功能:

? ? ? ? 實現IO多路復用

  • 參數

????????????????nfds? ? ? ? ? ? ? ? ? ? ? 文件描述符中最大文件描述符+1

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 遍歷時即可遍歷到自己? for(i = 0; i < nfds; i++)
????????????????readfds? ? ? ? ? ? ? ? ?讀操作的文件描述符的集合
????????????????writefds? ? ? ? ? ? ? ? 寫操作的文件描述符的集合
????????????????exceptfds? ? ? ? ? ? ?異常的文件描述符的集合
????????????????timeout? ? ? ? ? ? ? ? ?設置超時時間? ? ? ? ? ? ? ?struct timeval_t = {3, 0}; //阻塞3秒

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?NULL表示select是阻塞功能

????????????????????????????????????????????????????????????????0? ? ? ? ?-? 非阻塞

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? n > 0? -? 每次阻塞的時間

  • 返回值

? ? ? ? 成功返回就緒的文件描述符的數量

? ? ? ? 失敗返回-1

1. 輔助函數

void FD_CLR(int fd, fd set *set);? ? ? ? ? ? ? ? // 將fd從set集合中清除
int FD_ISSET(int fd, fd_set *set);???????????????// 判斷fd是否在set中
void FD_SET(int fd, fd_set *set);? ? ? ? ? ? ?// 將fd添加到set集合中
void FD_ZERO(fd_set *set);t*set); ????????????// 將set集合清空

2. 步驟

1. 建立一張表? ? ? ? 監控

? ? ? ? fd_set readfds ;? ? ? ? ? ? ? ? ? ? ? ? 建立表

????????FD_ZERO(&readfds)? ? ? ? ? ? ? ? 清空表

2. 將要監控的文件描述符加入表中

????????FD_SET(0,&readfds);? ? ? ? ? ? ?0表示標準輸入

????????FD_SET(fd,&readfds);?

3.準備參數

????????nfds = fd + 1

? ? ? ? select(nfs, &readfds, NULL, NULL, NULL);

4. 監控文件描述符

3. 缺點

1.最大監聽數受限:FD_SETSIZE 默認1024(Linux)
2.每次調用需重置fdSet:內核會修改集合,必須每次重新
3.用戶態與內核態拷貝開銷大
4.返回后仍需遍歷所有fd才能知道哪個就緒
5.效率隨fd數量增長下降明顯

4. 點對點聊天

server.c:

client.c:

超時設置:

5. 多路IO復用

server.c

client.c:

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????(退出.quit不管用)

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 解決:?使用strncpy函數除去輸入的\n

2. poll

  • 原型:int poll(struct pollfd *fds, nfds_t nfds, int timeout);

????????struct pollfd {
? ? ? ? ? ? ? ?int ? fd; ? ? ? ? /* file descriptor */
? ? ? ? ? ? ? ?short events; ? ? /* requested events */
? ? ? ? ? ? ? ?short revents; ? ?/* returned events */
? ? ? ? ? ?};

  • 功能:

? ? ? ? 對文件描述符監控

  • 參數:

? ? ? ? ? ? ? ?events? ? ? ? ? ? ? ? 事件:POLLIN? ? ? ? 讀

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? POLLOUT? ? ?寫

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? POLLERR? ? ?錯誤
? ? ? ? ? ? ? ?revents? ? ? ? ? ? ? ? 返回就緒的事件

? ? ? ? ? ? ? ? nfds? ? ? ? ? ? ? ? ? ? 監控的文件描述符的個數

? ? ? ? ? ? ? ? timeout? ? ? ? ? ? ? ? 時間值,-1阻塞? ? ? ? 時間值,單位ms

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0非阻塞

  • 返回值

? ? ? ? 成功返回就緒文件的數量,0 超時情況下沒有就緒事件

? ? ? ? 失敗返回 -1

1. 步驟

1. 建立監控表? ? ? ??

? ? ? ? struct pollfd fds[10];? ? ? ? // 監控10個fd

2. 將要監控的文件描述符加入表中

? ? ? ? 兩路:int nfds = 0;

? ? ? ? ? ? ? ? ? ?fds[0].fd = 0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fds[1].fd = sockfd;

? ? ? ? ? ? ? ? ? ?fds[0].events = POLLIN | POLLOUT;? ? ? ? ? fds[0].events = POLLIN | POLLOUT;

? ? ? ? ? ? ? ? ? ?nfds++;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nfds++;

? ? ? ? ? ? ? ? ? ?// 關心讀和寫,只會返回就緒的事件

3.準備參數

4. 監控文件描述符

2. 改進與缺點
  • 相比select的改進

1.無1024限制:只要系統允許打開足夠多fd
2.無需重置集合:^events和」revents丶分離
3.更清晰的事件機制
4.效率更高:僅遍歷傳入的數組,不遍歷整個fd范圍

  • 仍存在的問題

1.每次調用仍需將整個fds[]拷貝到內核
2.返回后仍需遍歷全部元素查找就緒fd
3.時間復雜度仍是O(n),連接數多時性能下降

3. 點對點聊天

server.c:

client.c:

4. 多路IO復用

server.c:


3. epoll

1. epoll_create
  • 原型:int epoll_create(int size)
  • 功能:

? ? ? ? 創建一個epoll對象

  • 參數:

? ? ? ? size? ? ? ? 忽略,但是必須大于0

  • 返回值

? ? ? ? 成功返回epoll對象的fd

? ? ? ? 失敗返回-1

2. epoll_ctl
  • 原型:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
  • 功能:

? ? ? ? 控制epoll對象

  • 參數:

? ? ? ? epfd? ? ? ? ? ? ? ? ? ? ? ? ? epoll對象的fd

????????op? ? ? ? ? ? ? ? ? ??EPOLL_CTL_ADD? ? ? ? ?添加

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??EPOLL_CTL_MOD? ? ? ? 修改

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? EPOLL_CTL_DEL? ? ? ? ? 刪除

????????fd? ? ? ? ? ? ? ? ? ? ?????????關心的文件描述符

????????event? ? ? ? ? ? ? ?事件?? ? ? ? ? ? ? ?

????????????????????????????????typedef union epoll_data {
? ? ? ? ? ? ? ?????????????????????????void? ? ? ? ? ?*ptr;
? ? ? ? ? ? ? ?????????????????????????int? ? ? ? ? ? ? ?fd;
? ? ? ? ? ? ????????????????????????? ?uint32_t ? ? u32;
? ? ? ? ????????????????????????? ? ? ?uint64_t ? ? u64;
? ? ? ? ??????????????????????? } epoll_data_t;

? ? ? ? ? ?-------------------------------------------------------------------------------------------------------

????????????????????????????????struct epoll_event {
? ? ? ? ? ? ????????????????????????? ?uint32_t ? ? events; ? ? ?// EPOLLIN? ? ? ? ? ? ? ? 讀

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //?EPOLLOUT? ? ? ? ? ? ?寫

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // EPOLLERR? ? ? ? ? ? ?出錯

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // EPOLLET? ? ? ? ? ? ? ? 邊沿觸發
? ? ? ? ? ? ??????????????????????????epoll_data_t data;? ? ? ??
? ? ? ? ? ??????????????????????};

  • 返回值

? ? ? ? 成功返回0,失敗返回-1

中斷

1. 水平(電平)觸發

? ? ? ? 有數據就會一直通知

2. 邊沿觸發

? ? ? ? 每完成從沒數據到有數據的過程,通知一次

3. epoll_wait
  • 原型:int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
  • 功能:

? ? ? ? 監控對應文件描述符,查看是否就緒

  • 參數:

????????epfd? ? ? ? ? ? ? ? ? ? epoll對象

????????events? ? ? ? ? ? ? ? 保存就緒結果的數組的首地址
????????maxevents? ? ? ? ? 數組大小

????????timeout? ? ? ? ? ? ? ? 設置超時時間,單位ms

  • 返回值:

? ? ? ? 成功返回就緒數量,失敗返回-1

4. 步驟

1. 創建一個epoll對象 -- 監控的表

? ? ? ? int epfd = epoll_create(2);

2. 添加文件描述符

? ? ? ? int add_fd(int fd, int epfd)

? ? ? ? {

? ? ? ? ????????struct epoll_event ev;

? ? ? ? ????????ev.events = EPOLLIN;

? ? ? ? ????????ev.data.fd = fd;

? ? ? ? ? ? ? ? if( epoll_ctl(epfd,EPOLL_CTL_ADD, fd, &ev) < 0)

? ? ? ? ? ? ? ? {? ? ? ? perror("fail to add");? ? ? ? return -1;}

? ? ? ? ? ? ? ? return 0;

????????}

????????add_fd(0,?epfd);

????????add_fd(fd,?epfd);

刪除文件描述符

????????int del_fd(int fd, int epfd)?
????????{
?? ?????????if ( epoll_ctl(epfd,EPOLL_CTL_DEL, fd, NULL))
?? ?????????{????????perror("fail to delte");????????return -1;?}?? ?
?????????? ?return 0;
????????}

?3. 監控文件描述符

5. 點對點聊天

server.c

client.c


半包

想要接受4000的數據,但網絡層一次只能打包1500字節的數據

解決:多接受幾次,注意越界判斷

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

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

相關文章

Mybatis中緩存機制的理解以及優缺點

文章目錄一、MyBatis 緩存機制詳解1. 一級緩存&#xff08;Local Cache&#xff09;2. 二級緩存&#xff08;Global Cache&#xff09;3. 緩存執行順序二、MyBatis 緩存的優點三、MyBatis 緩存的缺點四、適用場景與最佳實踐總結MyBatis 提供了完善的緩存機制&#xff0c;用于減…

Rust 登堂 之 類型轉換(三)

Rust 是類型安全的語言&#xff0c;因此在Rust 中做類型轉換不是一件簡單的事&#xff0c;這一章節&#xff0c;我們將對Rust 中的類型轉換進行詳盡講解。 高能預警&#xff0c;本章節有些難&#xff0c;可以考慮學了進階后回頭再看 as 轉換 先來看一段代碼 fn main() {let a…

【MySQL 為什么默認會給 id 建索引? MySQL 主鍵索引 = 聚簇索引?】

MySQL 索引 MySQL 為什么默認會給 id 建索引&#xff1f; & MySQL 主鍵索引 聚簇索引&#xff1f; 結論&#xff1a;在 MySQL (InnoDB) 中&#xff0c;主鍵索引是自動創建的聚簇索引&#xff0c;不需要刪除&#xff0c;其他索引是補充優化。 1. MySQL 的id 索引是怎么來的…

[光學原理與應用-321]:皮秒深紫外激光器產品不同階段使用的工具軟件、對應的輸出文件

在皮秒深紫外激光器的開發過程中&#xff0c;不同階段使用的工具軟件及其對應的輸出文件如下&#xff1a;一、設計階段工具軟件&#xff1a;Zemax OpticStudio&#xff1a;用于光學系統的初步設計和仿真&#xff0c;包括光線追跡、像差分析、優化設計等。MATLAB&#xff1a;用于…

openEuler常用操作指令

openEuler常用操作指令 一、前言 1.簡介 openEuler是由開放原子開源基金會孵化的全場景開源操作系統項目&#xff0c;面向數字基礎設施四大核心場景&#xff08;服務器、云計算、邊緣計算、嵌入式&#xff09;&#xff0c;全面支持ARM、x86、RISC-V、loongArch、PowerPC、SW…

Python爬蟲實戰:構建網易云音樂個性化音樂播放列表同步系統

1. 引言 1.1 研究背景 在數字音樂生態中,各大音樂平臺憑借獨家版權、個性化推薦等優勢占據不同市場份額。根據國際唱片業協會(IFPI)2024 年報告,全球流媒體音樂用戶已突破 50 億,其中超過 60% 的用戶同時使用 2 個及以上音樂平臺。用戶在不同平臺積累的播放列表包含大量…

vscode 配置 + androidStudio配置

插件代碼片段 餓了么 icon{"Print to console": {"prefix": "ii-ep-","body": ["i-ep-"],"description": "elementPlus Icon"} }Ts 初始化模版{"Print to console": {"prefix": &q…

DQN(深度Q網絡):深度強化學習的里程碑式突破

本文由「大千AI助手」原創發布&#xff0c;專注用真話講AI&#xff0c;回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我&#xff0c;一起撕掉過度包裝&#xff0c;學習真實的AI技術&#xff01; ? 1. DQN概述&#xff1a;當深度學習遇見強化學習 DQN&#xff08;D…

個人博客運行3個月記錄

個人博客 自推一波&#xff0c;目前我的Hexo個人博客已經優化的足夠好了&#xff0c; 已經足夠穩定的和簡單進行發布和管理&#xff0c;但還是有不少問題&#xff0c;總之先記下來再說 先總結下 關于評論系統方面&#xff0c;我從Waline (快速上手 | Waline) 更換成了&#x…

C89標準關鍵字以及運算符分類匯總

開發單片機項目學好C語言尤其重要&#xff0c;我感覺學習C語言需要先學好關鍵字和運算符&#xff0c;我對C語言的關鍵字和運算符做一下匯總。一、關鍵字&#xff1a;&#xff08;C89標準一共有32個關鍵字&#xff09;(1) 數據類型關鍵字&#xff08;一共12個&#xff0c;分為基…

吱吱企業通訊軟件打破跨部門溝通壁壘,為企業搭建安全的通訊環境

在數字化轉型浪潮中&#xff0c;企業通訊軟件不再僅僅作為企業跨部門溝通橋梁&#xff0c;更是承載著保護通訊數據安全的使命。吱吱企業通訊憑借其“私有化部署全鏈路加密”雙重機制&#xff0c;為企業構建了一套“溝通便捷、通訊安全”的數字化通訊解決方案。 一、打破溝通壁壘…

Day16_【機器學習建模流程】

一、機器學習建模流程&#xff1a;獲取數據&#xff08;搜集與完成機器學習任務相關的數據集&#xff09;數據基本處理&#xff08;數據 缺失值處理&#xff0c;異常值處理&#xff09;特征工程&#xff08;特征提取、特征預處理 、特征降維、特征選擇 、特征組合&#xff09;機…

【不說廢話】pytorch中.to(device)函數詳解

1. 這個函數是什么&#xff1f; .to(device) 是 PyTorch 中一個用于張量和模型在設備&#xff08;CPU 或 GPU&#xff09;之間移動的核心函數。這里的 “設備” &#xff08;device&#xff09; 通常指的是計算發生的硬件位置&#xff0c;最常見的是&#xff1a; CPU&#xff1…

基于matplotlib庫的python可視化:以北京市各區降雨量為例

一、實驗目的1. 掌握使用Python的pandas、matplotlib和seaborn庫進行數據可視化的方法 2. 學習制作杠鈴圖、堆積柱狀圖和折線圖等多種圖表類型 3. 分析北京市各區在特定時間段內的降雨量的變化規律 4. 培養數據分析和可視化的實踐能力二、實驗數據數據來源&#xff1a;北京市水…

SCDN如何提示網站性能和安全防護

SCDN&#xff08;Secure Content Delivery Network&#xff0c;安全內容分發網絡&#xff09;是融合了傳統 CDN&#xff08;內容分發網絡&#xff09;性能加速能力與專業安全防護能力的新一代網絡服務&#xff0c;核心目標是在 “快速分發內容” 的基礎上&#xff0c;同步解決網…

PowerShell遠程加載Mimikatz完全指南:從原理到實戰

PowerShell遠程加載Mimikatz完全指南&#xff1a;從原理到實戰無文件攻擊技術是現代滲透測試的核心技能&#xff0c;掌握PowerShell遠程加載Mimikatz對白帽子黑客至關重要1 引言 在當今的網絡安全領域&#xff0c;無文件攻擊(fileless attack)已成為高級持久性威脅(APT)的主要手…

基于Spring Boot的民宿服務管理系統-項目分享

基于Spring Boot的民宿服務管理系統-項目分享項目介紹項目摘要系統總體結構圖民宿資訊信息實體圖項目預覽民宿信息管理頁面民宿咨詢管理頁面已支付訂單管理頁面用戶主頁面寫在最后項目介紹 使用者&#xff1a;管理員、用戶 開發技術&#xff1a;MySQLJavaSpringBootVue 項目摘…

SpringBoot基礎知識-從XML配置文件到Java Config

項目結構與依賴首先&#xff0c;我們需要添加 Spring 核心依賴&#xff1a;<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.5.RELEASE</version> </dependency>項目…

用無標簽語音自我提升音頻大模型:SI-SDA 方法詳解

用無標簽語音自我提升音頻大模型:SI-SDA 方法詳解 在語音識別和處理領域,近年來大模型(Large Language Models, LLMs)的發展迅速,為語音任務帶來了新的突破。然而,語音信號的復雜性使得這些模型在特定領域中表現不佳。如何在沒有標注數據的情況下提升音頻大模型的表現?…

開源工具新玩法:cpolar提升Penpot協作流暢度

文章目錄前言1. 安裝Docker2. Docker鏡像源添加方法3. 創建并啟動Penpot容器3. 本地使用Penpot進行創作4. 公網遠程訪問本地Penpot4.1 內網穿透工具安裝4.2 創建遠程連接公網地址5. 固定Penpot公網地址前言 你是否也曾因商業設計軟件的高昂費用而放棄團隊協作&#xff1f;或者…