《UNIX網絡編程卷1:套接字聯網API》第5章 TCP客戶服務器程序示例

《UNIX網絡編程卷1:套接字聯網API》第5章 TCP客戶/服務器程序示例


5.1 本章目標與示例程序概述

本章通過一個完整的TCP回射(Echo)客戶/服務器程序,深入解析TCP套接字編程的核心流程與關鍵問題。示例程序的功能為:客戶端發送文本至服務器,服務器將文本原樣返回。通過此案例,讀者將掌握:

  1. TCP通信全流程:從套接字創建到連接終止;
  2. 并發服務器設計:多進程/多線程模型實現;
  3. 健壯性處理:應對網絡異常與資源管理;
  4. 調試技巧:使用工具分析協議交互。

5.2 服務器端程序實現
5.2.1 主函數框架
#include "unp.h"int main(int argc, char **argv) {int listenfd, connfd;pid_t childpid;socklen_t clilen;struct sockaddr_in cliaddr, servaddr;// 創建TCP套接字listenfd = Socket(AF_INET, SOCK_STREAM, 0);// 初始化服務器地址結構bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 綁定所有接口servaddr.sin_port = htons(SERV_PORT);         // 服務端口號// 綁定與監聽Bind(listenfd, (SA *)&servaddr, sizeof(servaddr));Listen(listenfd, LISTENQ); // LISTENQ定義連接隊列最大長度for (;;) {clilen = sizeof(cliaddr);connfd = Accept(listenfd, (SA *)&cliaddr, &clilen); // 阻塞等待連接// 并發處理if ((childpid = Fork()) == 0) { // 子進程Close(listenfd);           // 子進程關閉監聽套接字str_echo(connfd);          // 處理客戶端請求exit(0);}Close(connfd); // 父進程關閉已連接套接字}
}

關鍵點

  • INADDR_ANY允許服務器監聽所有網絡接口;
  • fork()實現并發處理,父進程繼續監聽新連接,子進程處理當前連接。
5.2.2 數據回射函數str_echo
void str_echo(int sockfd) {ssize_t n;char buf[MAXLINE];
again:while ((n = Read(sockfd, buf, MAXLINE)) > 0)Writen(sockfd, buf, n); // 回射數據if (n < 0 && errno == EINTR) // 處理中斷goto again;else if (n < 0)err_sys("str_echo: read error"); // 包裹函數處理錯誤
}

注意:TCP是字節流協議,需處理部分讀寫與粘包問題。


5.3 客戶端程序實現
5.3.1 主函數框架
#include "unp.h"int main(int argc, char **argv) {int sockfd;struct sockaddr_in servaddr;if (argc != 2)err_quit("usage: tcpcli <IPaddress>");// 創建TCP套接字sockfd = Socket(AF_INET, SOCK_STREAM, 0);// 初始化服務器地址bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SERV_PORT);Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);// 發起連接Connect(sockfd, (SA *)&servaddr, sizeof(servaddr));// 處理用戶輸入與服務器響應str_cli(stdin, sockfd); exit(0);
}

關鍵點

  • Connect觸發三次握手,需處理ETIMEDOUT(超時)和ECONNREFUSED(拒絕連接)等錯誤。
5.3.2 用戶交互函數str_cli
void str_cli(FILE *fp, int sockfd) {char sendline[MAXLINE], recvline[MAXLINE];while (Fgets(sendline, MAXLINE, fp) != NULL) { // 讀取標準輸入Writen(sockfd, sendline, strlen(sendline)); // 發送至服務器if (Readline(sockfd, recvline, MAXLINE) == 0) // 讀取響應err_quit("str_cli: server terminated prematurely");Fputs(recvline, stdout); // 輸出響應}
}

說明Readline需正確處理部分讀與緩沖區管理(參考第3章字節流處理)。


5.4 并發服務器模型與僵尸進程處理
5.4.1 多進程模型的缺陷
  • 僵尸進程:子進程終止后未調用wait,導致進程表中殘留條目;
  • 資源泄漏:未關閉套接字可能耗盡文件描述符。
5.4.2 解決方案:信號處理
void sig_chld(int signo) {pid_t pid;int stat;while ((pid = waitpid(-1, &stat, WNOHANG)) > 0)printf("child %d terminated\n", pid);return;
}// 主函數中注冊信號處理
Signal(SIGCHLD, sig_chld); // 使用包裹函數處理信號

作用:捕獲SIGCHLD信號,回收子進程資源。


5.5 異常場景分析與處理
5.5.1 服務器主機崩潰
  • 現象:客戶端read阻塞,TCP持續重傳數據,最終返回ETIMEDOUT
  • 處理:設置超時機制或使用心跳包檢測連接狀態。
5.5.2 服務器主機重啟
  • 現象:客戶端收到ECONNRESET錯誤;
  • 處理:重連機制或優雅終止程序。
5.5.3 客戶端非正常終止
  • 現象:服務器子進程read返回0,觸發正常關閉流程;
  • 處理:確保close釋放資源,避免文件描述符泄漏。

5.6 測試與調試技巧
5.6.1 使用netstat監控連接狀態
netstat -ant | grep 9999 # 查看端口9999的TCP連接狀態

輸出示例

  • LISTEN:監聽狀態;
  • ESTABLISHED:已建立連接;
  • TIME_WAIT:連接終止等待。
5.6.2 tcpdump抓包分析
tcpdump -i lo port 9999 # 監聽本地回環接口的9999端口

關鍵字段

  • SYN/ACK:三次握手過程;
  • FIN:四次揮手過程。
5.6.3 使用ps查看進程狀態
ps -ef | grep tcpserv # 查看服務器進程狀態

狀態說明

  • S:睡眠狀態(等待I/O);
  • Z:僵尸進程。

5.7 性能優化與擴展
5.7.1 線程池模型
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // 線程分離
pthread_create(&tid, &attr, handle_client, (void *)connfd);

優勢:避免頻繁創建/銷毀線程的開銷。

5.7.2 I/O復用(select/epoll
  • 適用場景:高并發連接,減少進程/線程切換開銷;
  • 實現要點:事件驅動模型,非阻塞I/O。
  • 參見相關文章:epoll函數使用實戰詳解

5.8 本章小結與進階習題

小結:本章通過Echo程序完整演示了TCP客戶/服務器開發流程,涵蓋并發模型、異常處理與調試技巧,為復雜網絡應用開發奠定基礎。

習題

  1. 實現UDP版本的Echo程序,對比TCP/UDP編程差異;
  2. 修改服務器為線程池模型,測試并發性能;
  3. 使用Wireshark分析TCP握手與揮手過程,提交抓包分析報告。

付費用戶專屬資源

  • 完整代碼工程(含Makefile與測試腳本);
  • TCP狀態轉換圖(矢量圖);
  • 擴展閱讀:《UNIX網絡編程中的并發模型演進》。

通過本章學習,讀者將掌握TCP套接字編程的核心技術,并具備開發高可靠性、高并發網絡服務的能力。

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

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

相關文章

封裝可拖動彈窗(vue jquery引入到html的版本)

vue cli上簡單的功能&#xff0c;在js上太難弄了&#xff0c;這個彈窗功能時常用到&#xff0c;保存起來備用吧 備注&#xff1a;deepseek這個人工智障寫一堆有問題的我&#xff0c;還老服務器繁忙 效果圖&#xff1a; html代碼&#xff1a; <div class"modal-mask&qu…

編譯器工具鏈是什么?

編譯器工具鏈&#xff08;Compiler Toolchain&#xff09; 是一組用于將源代碼轉換為可執行程序的工具和庫的集合。它涵蓋了從源代碼編寫到程序運行的整個構建過程&#xff0c;包括編譯、匯編、鏈接等多個階段。以下是關于編譯器工具鏈的詳細解釋&#xff1a; 一、編譯器工具鏈…

Spring Boot 集成Redis中 RedisTemplate 及相關操作接口對比與方法說明

RedisTemplate 及相關操作接口對比與方法說明 1. RedisTemplate 核心接口與實現類 RedisTemplate 是 Spring Data Redis 的核心模板類&#xff0c;通過 opsFor... 方法返回不同數據類型的操作接口&#xff0c;每個接口對應 Redis 的一種數據結構。以下是主要接口及其實現類&am…

linux內核漏洞檢測利用exp提權

案例一dirtycow&#xff08;CVE-2016-5159&#xff09; 有個前置知識就是 獲取liunx的內核 hostnamectl uname -a 然后這個內核漏洞進行提權的步驟也是和手工win進行提權差不多 也是需要使用輔助工具在本地進行輔助檢測 然后去nomi-sec/PoC-in-GitHub&#xff1a; &#…

重磅 | CertiK《Hack3d:2025第一季度安全報告》(附報告全文鏈接)

CertiK《Hack3d&#xff1a;2025年第一季度安全報告》現已發布&#xff0c;本次報告深入分析了2025年1至3月Web3.0領域的安全狀況。2025年第一季度共發生197起安全事件&#xff0c;總損失約為16.7億美元&#xff0c;環比激增303.4%。其中Bybit事件導致約14.5億美元的損失&#…

經典卷積神經網絡LeNet實現(pytorch版)

LeNet卷積神經網絡 一、理論部分1.1 核心理論1.2 LeNet-5 網絡結構1.3 關鍵細節1.4 后期改進1.6 意義與局限性二、代碼實現2.1 導包2.1 數據加載和處理2.3 網絡構建2.4 訓練和測試函數2.4.1 訓練函數2.4.2 測試函數2.5 訓練和保存模型2.6 模型加載和預測一、理論部分 LeNet是一…

二維碼掃不出?用QR Research工具

一.簡介 簡單來說QR Research就是用來掃二維碼的工具 當二維碼模糊不清&#xff0c;無法用普通方式掃時&#xff0c;就可以用QR Research輕松掃描。QR Research還可以分析變形/破損二維碼&#xff08;修復或提取有效部分&#xff09; 二.下載安裝 QR Research 三.例題 這…

02_使用Docker在服務器上部署Jekins實現項目的自動化部署

02_使用Docker在服務器上部署jenkins實現項目的自動化部署 一、使用docker拉取阿里云容器私有鏡像倉庫內的jenkins鏡像 登錄阿里云Docker Registry $ sudo docker login --usernamewxxxo1xxx registry.cn-shanghai.aliyuncs.com用于登錄的用戶名為阿里云賬號全名&#xff0c…

微服務組件——Eureka組件的安裝與使用指南

文章目錄 一、Eureka Server的安裝與配置1、創建Spring Boot項目2、添加依賴3、配置Eureka Server4、啟用Eureka Server5、啟動并訪問Dashboard 二、Eureka Client的配置&#xff08;服務注冊&#xff09;1、添加客戶端依賴2、配置客戶端3、啟用服務發現4、啟動服務 三、服務發…

探索Doris:日志分析的新寵,是否能取代老牌ES?

在大數據時代&#xff0c;日志存儲與分析對于企業的運營和決策起著至關重要的作用。Elasticsearch&#xff08;簡稱 ES&#xff09;作為一款廣泛應用的開源分布式搜索和分析引擎&#xff0c;長期以來在日志管理領域占據著舉足輕重的地位。然而&#xff0c;隨著技術的不斷發展&a…

學習threejs,使用Texture紋理貼圖,測試repeat重復紋理貼圖

&#x1f468;??? 主頁&#xff1a; gis分享者 &#x1f468;??? 感謝各位大佬 點贊&#x1f44d; 收藏? 留言&#x1f4dd; 加關注?! &#x1f468;??? 收錄于專欄&#xff1a;threejs gis工程師 文章目錄 一、&#x1f340;前言1.1 ??Texture 紋理貼圖1.1.1 ??…

圖像配準及識別

一、圖像配準基礎 圖像配準&#xff0c;聽起來很高大上&#xff0c;其實用大白話來說&#xff0c;就是“讓兩張照片對齊”的技術。想象一下&#xff0c;你有兩張拍得不完全一樣的照片&#xff0c;比如一張是你從正面拍的風景&#xff0c;另一張是從側面拍的同一個地方&#xff…

QT之QML(簡單示例)

需求一&#xff1a;點擊按鈕彈出菜單&#xff0c;并且自定義菜單彈出位置。 mouse.x 和 mouse.y 獲取的是相對于 MouseArea&#xff08;在這個例子中是 Button&#xff09;左上角的局部坐標。如果你想要在鼠標點擊位置顯示 Menu&#xff0c;你需要將這個局部坐標轉換為相對于應…

如何編寫單元測試

一、前言知識 1.開發過程 需求分析->設計->開發->測試->上線 2.測試種類 單元測試(測試模塊編碼)、黑盒測試(測試功能是否滿足需求)、白盒測試(測試程序內部的邏輯結構)、回歸測試(提出的缺陷進行二次驗證)、集成測試(測試主要的業務功能及模塊間的整合性)、系…

LeetCode 解題思路 30(Hot 100)

解題思路&#xff1a; 遞歸參數&#xff1a; 生成括號的對數 n、結果集 result、當前路徑 path、左括號數 open、右括號數 close。遞歸過程&#xff1a; 當當前路徑 path 的長度等于 n * 2 時&#xff0c;說明已經生成有效括號&#xff0c;加入結果集。若左括號數小于 n&…

【Golang】Windows系統鍵鼠空閑監測練習

在本文中&#xff0c;我們將練習如何使用Golang編寫一個簡單的Windows系統空閑時間監測工具。該工具能夠檢測系統的空閑時間&#xff0c;并在達到一定閾值時計數。 功能概述 監控鼠標和鍵盤的空閑事件&#xff0c;每空閑超過50s&#xff0c;觸發次數加一。 該工具具有以下功…

關于React Redux

官網&#xff1a;&#x1f449;詳情一 &#x1f449;詳情二 &#x1f449;關于redux 使用原因&#xff1a;&#x1f449;詳情 /** 2-1、隨著javascript單頁應用程序的發展&#xff0c;需要在代碼中管理更多的狀態&#xff08;包括服務器響應數據、緩存數據、本地創建還未發送…

MySQL和Oracle批量插入SQL差異詳解

文章目錄 MySQL和Oracle批量插入SQL差異詳解1. 基本批量插入語法1.1 MySQL批量插入1.2 Oracle批量插入 2. 帶序列的批量插入2.1 MySQL帶自增ID的批量插入2.2 Oracle帶序列的批量插入 3. 條件批量插入3.1 MySQL條件批量插入3.2 Oracle條件批量插入 MySQL和Oracle批量插入SQL差異…

43頁可編輯PPT | 大數據管理中心設計規劃方案大數據中心組織架構大數據組織管理

這份文檔是一份關于大數據管理中心規劃設計方案的詳細報告&#xff0c;涵蓋了背景與需求分析、整體規劃方案、關鍵能力實現方案以及實施方案等內容。報告強調大數據在城市治理中的重要性&#xff0c;提出通過構建統一的大數據平臺&#xff0c;整合城市各部門數據資源&#xff0…

Python-八股總結

目錄 1 python 垃圾處理機制2 yield3 python 多繼承&#xff0c;兩個父類有同名方法怎么辦&#xff1f;4 python 多線程/多進程/協程4.1 多線程與GIL全局解釋器鎖4.2 多進程4.3 協程 5 樂觀鎖/悲觀鎖6 基本數據結構**1. 列表&#xff08;List&#xff09;****2. 元組&#xff0…