Linux多綫程服務端編程 使用muduo C++網絡庫

Linux多綫程服務端編程 使用muduo C++網絡庫 pdf epub mobi txt 电子书 下载 2025

陳碩 著
圖書標籤:
  • Linux
  • 多綫程
  • 服務端編程
  • muduo
  • C++
  • 網絡編程
  • 網絡庫
  • 高性能
  • 並發編程
  • 係統編程
想要找书就要到 求知書站
立刻按 ctrl+D收藏本页
你会得到大惊喜!!
出版社: 电子工业出版社
ISBN:9787121192821
版次:1
商品编码:11163782
品牌:Broadview
包装:平装
开本:16开
出版时间:2013-01-01
用纸:胶版纸
页数:616
正文语种:中文

具体描述

編輯推薦

  

多年編寫生産環境下多綫程服務端程序經驗之精華,示範在多核時代采用現代C++編寫多綫程TCP網絡服務器的正規做法

內容簡介

  《Linux多綫程服務端編程 使用muduoC++網絡庫》主要講述采用現代C++在x86-64Linux上編寫多綫程TCP網絡服務程序的主流常規技術,重點講解一種適應性較強的多綫程服務器的編程模型,即oneloopperthread。這是在Linux下以native語言編寫用戶態高性能網絡程序成熟的模式,掌握之後可順利地開發各類常見的服務端網絡應用程序。本書以muduo網絡庫為例,講解這種編程模型的使用方法及注意事項。
  《Linux多綫程服務端編程 使用muduoC++網絡庫》的宗旨是貴精不貴多。掌握兩種基本的同步原語就可以滿足各種多綫程同步的功能需求,還能寫齣更易用的同步設施。掌握一種進程間通信方式和一種多綫程網絡編程模型就足以應對日常開發任務,編寫運行於公司內網環境的分布式服務係統。

作者簡介

  陳碩,北京師範大學碩士,擅長C++ 多綫程網絡編程和實時分布式係統架構。曾在摩根士丹利IT 部門工作5 年,從事實時外匯交易係統開發。現在在美國加州矽榖某互聯網大公司工作,從事大規模分布式係統的可靠性工程。編寫瞭開源C++ 網絡庫muduo,參與翻譯瞭《代碼大全(第2 版)》和《C++ 編程規範(繁體版)》,整理瞭《C++ Primer (第4 版)(評注版)》,並曾多次在各地技術大會演講。

目錄

第1 部分 C++ 多綫程係統編程
第1 章 綫程安全的對象生命期管理
1.1 當析構函數遇到多綫程
1.1.1 綫程安全的定義
1.1.2 MutexLock 與MutexLockGuard
1.1.3 一個綫程安全的Counter 示例
1.2 對象的創建很簡單.
1.3 銷毀太難
1.3.1 mutex 不是辦法
1.3.2 作為數據成員的mutex 不能保護析構.
1.4 綫程安全的Observer 有多難.
1.5 原始指針有何不妥.
1.6 神器shared_ptr/weak_ptr
1.7 插麯:係統地避免各種指針錯誤.
1.8 應用到Observer 上
1.9 再論shared_ptr 的綫程安全.
1.10 shared_ptr 技術與陷阱
1.11 對象池.
1.11.1 enable_shared_from_this
1.11.2 弱迴調.
1.12 替代方案
1.13 心得與小結.
1.14 Observer 之謬.
第2 章 綫程同步精要
2.1 互斥器(mutex) .
2.1.1 隻使用非遞歸的mutex
2.1.2 死鎖
2.2 條件變量(condition variable) .
2.3 不要用讀寫鎖和信號量
2.4 封裝MutexLock、MutexLockGuard、Condition
2.5 綫程安全的Singleton 實現
2.6 sleep(3) 不是同步原語
2.7 歸納與總結.
2.8 藉shared_ptr 實現copy-on-write
第3 章 多綫程服務器的適用場閤與常用編程模型
3.1 進程與綫程.
3.2 單綫程服務器的常用編程模型
3.3 多綫程服務器的常用編程模型
3.3.1 one loop per thread
3.3.2 綫程池.
3.3.3 推薦模式
3.4 進程間通信隻用TCP .
3.5 多綫程服務器的適用場閤.
3.5.1 必須用單綫程的場閤.
3.5.2 單綫程程序的優缺點.
3.5.3 適用多綫程程序的場景
3.6 “多綫程服務器的適用場閤”例釋與答疑
第4 章 C++ 多綫程係統編程精要
4.1 基本綫程原語的選用.
4.2 C/C++ 係統庫的綫程安全性.
4.3 Linux 上的綫程標識
4.4 綫程的創建與銷毀的守則.
4.4.1 pthread_cancel 與C++ .
4.4.2 exit(3) 在C++ 中不是綫程安全的.
4.5 善用__thread 關鍵字.
4.6 多綫程與IO
4.7 用RAII 包裝文件描述符.
4.8 RAII 與fork() .
4.9 多綫程與fork() .
4.10 多綫程與signal
4.11 Linux 新增係統調用的啓示
第5 章 高效的多綫程日誌
5.1 功能需求
5.2 性能需求
5.3 多綫程異步日誌
5.4 其他方案

第2 部分 muduo 網絡庫
第6 章 muduo 網絡庫簡介
6.1 由來.
6.2 安裝.
6.3 目錄結構
6.3.1 代碼結構
6.3.2 例子
6.3.3 綫程模型
6.4 使用教程
6.4.1 TCP 網絡編程本質論.
6.4.2 echo 服務的實現.
6.4.3 七步實現finger 服務.
6.5 性能評測
6.5.1 muduo 與Boost.Asio、libevent2 的吞吐量對比
6.5.2 擊鼓傳花:對比muduo 與libevent2 的事件處理效率
6.5.3 muduo 與Nginx 的吞吐量對比.
6.5.4 muduo 與ZeroMQ 的延遲對比.
6.6 詳解muduo 多綫程模型.
6.6.1 數獨求解服務器
6.6.2 常見的並發網絡服務程序設計方案.
第7 章 muduo 編程示例
7.1 五個簡單TCP 示例
7.2 文件傳輸
7.3 Boost.Asio 的聊天服務器.
7.3.1 TCP 分包
7.3.2 消息格式
7.3.3 編解碼器LengthHeaderCodec
7.3.4 服務端的實現.
7.3.5 客戶端的實現.
7.4 muduo Buffer 類的設計與使用.
7.4.1 muduo 的IO 模型
7.4.2 為什麼non-blocking 網絡編程中應用層buffer 是必需的
7.4.3 Buffer 的功能需求
7.4.4 Buffer 的數據結構
7.4.5 Buffer 的操作.
7.4.6 其他設計方案.
7.4.7 性能是不是問題
7.5 一種自動反射消息類型的Google Protobuf 網絡傳輸方案
7.5.1 網絡編程中使用Protobuf 的兩個先決條件.
7.5.2 根據type name 反射自動創建Message 對象
7.5.3 Protobuf 傳輸格式
7.6 在muduo 中實現Protobuf 編解碼器與消息分發器
7.6.1 什麼是編解碼器(codec)
7.6.2 實現ProtobufCodec .
7.6.3 消息分發器(dispatcher)有什麼用
7.6.4 ProtobufCodec 與ProtobufDispatcher 的綜閤運用.
7.6.5 ProtobufDispatcher 的兩種實現
7.6.6 ProtobufCodec 和ProtobufDispatcher 有何意義.
7.7 限製服務器的最大並發連接數
7.7.1 為什麼要限製並發連接數
7.7.2 在muduo 中限製並發連接數
7.8 定時器.
7.8.1 程序中的時間.
7.8.2 Linux 時間函數
7.8.3 muduo 的定時器接口.
7.8.4 Boost.Asio Timer 示例
7.8.5 Java Netty 示例
7.9 測量兩颱機器的網絡延遲和時間差.
7.10 用timing wheel 踢掉空閑連接
7.10.1 timing wheel 原理
7.10.2 代碼實現與改進
7.11 簡單的消息廣播服務.
7.12 “串並轉換”連接服務器及其自動化測試
7.13 socks4a 代理服務器
7.13.1 TCP 中繼器
7.13.2 socks4a 代理服務器
7.13.3 N : 1 與1 : N 連接轉發
7.14 短址服務
7.15 與其他庫集成.
7.15.1 UDNS .
7.15.2 c-ares DNS .
7.15.3 curl .
7.15.4 更多
第8 章 muduo 網絡庫設計與實現
8.0 什麼都不做的EventLoop .
8.1 Reactor 的關鍵結構
8.1.1 Channel class .
8.1.2 Poller class
8.1.3 EventLoop 的改動.
8.2 TimerQueue 定時器
8.2.1 TimerQueue class .
8.2.2 EventLoop 的改動.
8.3 EventLoop::runInLoop() 函數
8.3.1 提高TimerQueue 的綫程安全性.
8.3.2 EventLoopThread class
8.4 實現TCP 網絡庫
8.5 TcpServer 接受新連接
8.5.1 TcpServer class
8.5.2 TcpConnection class .
8.6 TcpConnection 斷開連接.
8.7 Buffer 讀取數據
8.7.1 TcpConnection 使用Buffer 作為輸入緩衝.
8.7.2 Buffer::readFd()
8.8 TcpConnection 發送數據.
8.9 完善TcpConnection
8.9.1 SIGPIPE
8.9.2 TCP No Delay 和TCP keepalive
8.9.3 WriteCompleteCallback 和HighWaterMarkCallback .
8.10 多綫程TcpServer .
8.11 Connector .
8.12 TcpClient .
8.13 epoll
8.14 測試程序一覽.

第3 部分 工程實踐經驗談
第9 章 分布式係統工程實踐
9.1 我們在技術浪潮中的位置.
9.1.1 分布式係統的本質睏難
9.1.2 分布式係統是個險惡的問題.
9.2 分布式係統的可靠性淺說.
9.2.1 分布式係統的軟件不要求7 24 可靠
9.2.2 “能隨時重啓進程”作為程序設計目標.
9.3 分布式係統中心跳協議的設計
9.4 分布式係統中的進程標識.
9.4.1 錯誤做法
9.4.2 正確做法
9.4.3 TCP 協議的啓示
9.5 構建易於維護的分布式程序.
9.6 為係統演化做準備.
9.6.1 可擴展的消息格式
9.6.2 反麵教材:ICE 的消息打包格式.
9.7 分布式程序的自動化迴歸測試
9.7.1 單元測試的能與不能.
9.7.2 分布式係統測試的要點
9.7.3 分布式係統的抽象觀點
9.7.4 一種自動化的迴歸測試方案.
9.7.5 其他用處
9.8 分布式係統部署、監控與進程管理的幾重境界.
9.8.1 境界1:全手工操作.
9.8.2 境界2:使用零散的自動化腳本和第三方組件.
9.8.3 境界3:自製機群管理係統,集中化配置.
9.8.4 境界4:機群管理與naming service 結閤.
第10 章 C++ 編譯鏈接模型精要
10.1 C 語言的編譯模型及其成因.
10.1.1 為什麼C 語言需要預處理
10.1.2 C 語言的編譯模型.
10.2 C++ 的編譯模型
10.2.1 單遍編譯
10.2.2 前嚮聲明
10.3 C++ 鏈接(linking) .
10.3.1 函數重載
10.3.2 inline 函數.
10.3.3 模闆
10.3.4 虛函數.
10.4 工程項目中頭文件的使用規則
10.4.1 頭文件的害處.
10.4.2 頭文件的使用規則
10.5 工程項目中庫文件的組織原則
10.5.1 動態庫是有害的
10.5.2 靜態庫也好不到哪兒去
10.5.3 源碼編譯是王道
第11 章 反思C++ 麵嚮對象與虛函數
11.1 樸實的C++ 設計
11.2 程序庫的二進製兼容性
11.2.1 什麼是二進製兼容性.
11.2.2 有哪些情況會破壞庫的ABI .
11.2.3 哪些做法多半是安全的
11.2.4 反麵教材:COM .
11.2.5 解決辦法
11.3 避免使用虛函數作為庫的接口
11.3.1 C++ 程序庫的作者的生存環境
11.3.2 虛函數作為庫的接口的兩大用途
11.3.3 虛函數作為接口的弊端
11.3.4 假如Linux 係統調用以COM 接口方式實現
11.3.5 Java 是如何應對的
11.4 動態庫接口的推薦做法
11.5 以boost::function 和boost::bind 取代虛函數.
11.5.1 基本用途
11.5.2 對程序庫的影響
11.5.3 對麵嚮對象程序設計的影響.
11.6 iostream 的用途與局限
11.6.1 stdio 格式化輸入輸齣的缺點.
11.6.2 iostream 的設計初衷.
11.6.3 iostream 與標準庫其他組件的交互.
11.6.4 iostream 在使用方麵的缺點.
11.6.5 iostream 在設計方麵的缺點.
11.6.6 一個300 行的memory buffer output stream .
11.6.7 現實的C++ 程序如何做文件IO .
11.7 值語義與數據抽象.
11.7.1 什麼是值語義.
11.7.2 值語義與生命期
11.7.3 值語義與標準庫
11.7.4 值語義與C++ 語言
11.7.5 什麼是數據抽象
11.7.6 數據抽象所需的語言設施
11.7.7 數據抽象的例子
第12 章 C++ 經驗談
12.1 用異或來交換變量是錯誤的.
12.1.1 編譯器會分彆生成什麼代碼.
12.1.2 為什麼短的代碼不一定快
12.2 不要重載全局::operator new()
12.2.1 內存管理的基本要求.
12.2.2 重載::operator new() 的理由.
12.2.3 ::operator new() 的兩種重載方式.
12.2.4 現實的開發環境
12.2.5 重載::operator new() 的睏境.
12.2.6 解決辦法:替換malloc()
12.2.7 為單獨的class 重載::operator new() 有問題嗎.
12.2.8 有必要自行定製內存分配器嗎
12.3 帶符號整數的除法與餘數.
12.3.1 語言標準怎麼說
12.3.2 C/C++ 編譯器的錶現.
12.3.3 其他語言的規定
12.3.4 腳本語言解釋器代碼.
12.3.5 硬件實現
12.4 在單元測試中mock 係統調用
12.4.1 係統函數的依賴注入.
12.4.2 鏈接期墊片(link seam)
12.5 慎用匿名namespace .
12.5.1 C 語言的static 關鍵字的兩種用法.
12.5.2 C++ 語言的static 關鍵字的四種用法
12.5.3 匿名namespace 的不利之處.
12.5.4 替代辦法
12.6 采用有利於版本管理的代碼格式.
12.6.1 對diff 友好的代碼格式
12.6.2 對grep 友好的代碼風格.
12.6.3 一切為瞭效率.
12.7 再探std::string .
12.7.1 直接拷貝(eager copy) .
12.7.2 寫時復製(copy-on-write) .
12.7.3 短字符串優化(SSO)
12.8 用STL algorithm 輕鬆解決幾道算法麵試題
12.8.1 用next_permutation() 生成排列與組閤
12.8.2 用unique() 去除連續重復空白.
12.8.3 用{make,push,pop}_heap() 實現多路歸並
12.8.4 用partition() 實現“重排數組,讓奇數位於偶數前麵”
12.8.5 用lower_bound() 查找IP 地址所屬的城市.

第4 部分 附錄
附錄A 談一談網絡編程學習經驗
附錄B 從《C++ Primer(第4 版)》入手學習C++
附錄C 關於Boost 的看法
附錄D 關於TCP 並發連接的幾個思考題與試驗

精彩書摘

  附錄A
  談一談網絡編程學習經驗
  本文談一談我在學習網絡編程方麵的一些個人經驗。“網絡編程”這個術語的範圍很廣,本文指用Sockets API 開發基於TCP/IP 的網絡應用程序,具體定義見§A.1.5 “網絡編程的各種任務角色”。
  受限於本人的經曆和經驗,本附錄的適應範圍是:
  x86-64 Linux 服務端網絡編程,直接或間接使用Sockets API。
  公司內網。不一定是局域網,但總體位於公司防火牆之內,環境可控。
  本文可能不適閤:
  PC 客戶端網絡編程,程序運行在客戶的PC 上,環境多變且不可控。
  Windows 網絡編程。
  麵嚮公網的服務程序。
  高性能網絡服務器。
  本文分兩個部分:
  1. 網絡編程的一些“鬍思亂想”,以自問自答的形式談談我對這一領域的認識。
  2. 幾本必看的書,基本上還是W. Richard Stevents 的那幾本。
  另外,本文沒有特彆說明時均暗指TCP 協議,“連接”是“TCP 連接”,“服務
  端”是“TCP 服務端”。
  A.1 網絡編程的一些“鬍思亂想”
  以下大緻列齣我對網絡編程的一些想法,前後無關聯。
  A.1.1 網絡編程是什麼
  網絡編程是什麼?是熟練使用Sockets API 嗎?說實話,在實際項目裏我隻用過
  兩次Sockets API,其他時候都是使用封裝好的網絡庫。
  第一次是2005 年在學校做一個羽毛球賽場計分係統:我用C# 編寫運行在PC上的軟件,負責比分的顯示;再用C# 寫瞭運行在PDA 上的計分界麵,記分員拿著PDA 記錄比分;這兩部分程序通過TCP 協議相互通信。這其實是個簡單的分布式係統,體育館有幾片場地,每個場地都有一名拿PDA 的記分員,每個場地都有兩颱顯示比分的PC (顯示器是42 寸平闆電視,放在場地的對角,這樣兩邊看颱的觀眾都能看到比分)。這兩颱PC 的功能不完全一樣,一颱隻負責顯示當前比分,另一颱還要負責與PDA 通信,並更新數據庫裏的比分信息。此外,還有一颱PC 負責周期性地從數據庫讀齣全部7 片場地的比分,顯示在體育館牆上的大屏幕上。這颱PC 上還運行著一個程序,負責生成比分數據的靜態頁麵,通過FTP 上傳發布到某門戶網站的體育頻道。係統中還有一個錄入賽程(參賽隊、運動員、齣場順序等)數據庫的程序,運行在數據庫服務器上。算下來整個係統有十來個程序,運行在二十多颱設備(PC 和PDA)上,還要考慮可靠性,避免single point of failure。
  這是我第一次寫實際項目中的網絡程序,當時寫下來的感覺是像寫命令行與用戶交互的程序:程序在命令行輸齣一句提示語,等待客戶輸入一句話,然後處理客戶輸入,再輸齣下一句提示語,如此循環。隻不過這裏的“客戶”不是人,而是另一個程序。在建立好TCP 連接之後,雙方的程序都是read/write 循環(為求簡單,我用的是blocking 讀寫),直到有一方斷開連接。
  第二次是2010 年編寫mudu網絡庫,我再次拿起瞭Sockets API,寫瞭一個基於Reactor 模式的C++ 網絡庫。寫這個庫的目的之一就是想讓日常的網絡編程從Sockets API 的瑣碎細節中解脫齣來,讓程序員專注於業務邏輯,把時間用在刀刃上。mudu網絡庫的示例代碼包含瞭幾十個網絡程序,這些示例程序都沒有直接使用Sockets API。
  在此之外,無論是實習還是工作,雖然我寫的程序都會通過TCP 協議與其他程序打交道,但我沒有直接使用過Sockets API。對於TCP 網絡編程,我認為核心是處理“三個半事件”,見§6.4.1 “TCP 網絡編程本質論”。程序員的主要工作是在事件處理函數中實現業務邏輯,而不是和Sockets API“較勁”。
  這裏還是沒有說清楚“網絡編程”是什麼,請繼續閱讀後文§A.1.5“網絡編程的各種任務角色”。
  A.1.2 學習網絡編程有用嗎
  以上說的是比較底層的網絡編程,程序代碼直接麵對從TCP 或UDP 收到的數據以及構造數據包發齣去。在實際工作中,另一種常見的情況是通過各種client library來與服務端打交道,或者在現成的框架中填空來實現server,或者采用更上層的通信方式。比如用libmemcached 與memcached 打交道,使用libpq 來與PostgreSQL 打交道,編寫Servlet 來響應HTTP 請求,使用某種RPC 與其他進程通信,等等。這些情況都會發生網絡通信,但不一定算作“網絡編程”。如果你的工作是前麵列舉的這些,學習TCP/IP 網絡編程還有用嗎?
  我認為還是有必要學一學,至少在troubleshooting 的時候有用。無論如何,這些library 或framework 都會調用底層的Sockets API 來實現網絡功能。當你的程序遇到一個綫上問題時,如果你熟悉Sockets API,那麼從strace 不難發現程序卡在哪裏,盡管可能你沒有直接調用這些Sockets API。另外,熟悉TCP/IP 協議、會用tcpdump 也非常有助於分析解決綫上網絡服務問題。
  A.1.3 在什麼平颱上學習網絡編程
  對於服務端網絡編程,我建議在Linux 上學習。
  如果在10 年前,這個問題的答案或許是FreeBSD,因為FreeBSD“根正苗紅”,在2000 年那一次互聯網浪潮中扮演瞭重要角色,是很多公司首選的免費服務器操作係統。2000 年那會兒Linux 還遠未成熟,連epoll 都還沒有實現。(FreeBSD 在2001年發布4.1 版,加入瞭kqueue,從此C10k 不是問題。)
  10 年後的今天,事情起瞭一些變化,Linux 成為市場份額最大的服務器操作係統。在Linux 這種大眾係統上學網絡編程,遇到什麼問題會比較容易解決。因為用的人多,你遇到的問題彆人多半也遇到過;同樣因為用的人多,如果真的有什麼內核bug,很快就會得到修復,至少有work around 的辦法。如果用彆的係統,可能一個問題發到論壇上半個月都不會有人理。從內核源碼的風格看,FreeBSD 更乾淨整潔,注釋到位,但是無奈它的市場份額遠不如Linux,學習Linux 是更好的技術投資。
  A.1.4 可移植性重要嗎
  寫網絡程序要不要考慮移植性?要不要跨平颱?這取決於項目需要,如果貴公司做的程序要賣給其他公司,而對方可能使用Windows、Linux、FreeBSD、Solaris、AIX、HP-UX 等等操作係統,這時候當然要考慮移植性。如果編寫公司內部的服務器上用的網絡程序,那麼大可隻關注一個平颱,比如Linux。因為編寫和維護可移植的網絡程序的代價相當高,平颱間的差異可能遠比想象中大,即便是POSIX 係統之間也有不小的差異(比如Linux 沒有SO_NOSIGPIPE 選項,Linux 的pipe(2) 是單嚮的,而FreeBSD 是雙嚮的),錯誤的返迴碼也大不一樣。
  我就不打算把mudu往Windows 或其他操作係統移植。如果需要編寫可移植的網絡程序,我寜願用libevent、libuv、Java Netty 這樣現成的庫,把“髒活、纍活”留給彆人。
  A.1.5 網絡編程的各種任務角色
  計算機網絡是個big topic,涉及很多人物和角色,既有開發人員,也有運維人員。比方說:公司內部兩颱機器之間ping 不通,通常由網絡運維人員解決,看看是布綫有問題還是路由器設置不對;兩颱機器能ping 通,但是程序連不上,經檢查是本機防火牆設置有問題,通常由係統管理員解決;兩颱機器能連上,但是丟包很嚴重,發現是網卡或者交換機的網口故障,由硬件維修人員解決;兩颱機器的程序能連上,但是偶爾發過去的請求得不到響應,通常是程序bug,應該由開發人員解決。
  本文主要關心開發人員這一角色。下麵簡單列齣一些我能想到的跟網絡打交道的編程任務,其中前三項是麵嚮網絡本身,後麵幾項是在計算機網絡之上構建信息係統。
  1. 開發網絡設備,編寫防火牆、交換機、路由器的固件(firmware)。
  2. 開發或移植網卡的驅動。
  3. 移植或維護TCP/IP 協議棧(特彆是在嵌入式係統上)。
  4. 開發或維護標準的網絡協議程序,HTTP、FTP、DNS、SMTP、POP3、NFS。
  5. 開發標準網絡協議的“附加品”,比如HAProxy、squid、varnish 等Web loadbalancer。
  6. 開發標準或非標準網絡服務的客戶端庫,比如ZooKeeper 客戶端庫、memcached客戶端庫。
  7. 開發與公司業務直接相關的網絡服務程序,比如即時聊天軟件的後颱服務器、網遊服務器、金融交易係統、互聯網企業用的分布式海量存儲、微博發帖的內部廣播通知等等。
  8. 客戶端程序中涉及網絡的部分,比如郵件客戶端中與POP3、SMTP 通信的部分,以及網遊的客戶端程序中與服務器通信的部分。
  本文所指的“網絡編程”專指第7 項,即在TCP/IP 協議之上開發業務軟件。換句話說,不是用Sockets API 開發mudu這樣的網絡庫,而是用libevent、muduo、Netty、gevent 這樣現成的庫開發業務軟件,mudu自帶的十幾個示例程序是業務軟件的代錶。
  A.1.6 麵嚮業務的網絡編程的特點
  與通用的網絡服務器不同,麵嚮公司業務的專用網絡程序有其自身的特點。
  業務邏輯比較復雜,而且時常變化 如果寫一個HTTP 服務器,在大緻實現HTTP 1.1 標準之後,程序的主體功能一般不會有太大的變化,程序員會把時間放在性能調優和bug 修復上。而開發針對公司業務的專用程序時,功能說明書(spec)很可能不如HTTP 1.1 標準那麼細緻明確。更重要的是,程序是快速演化的。以即時聊天工具的後颱服務器為例,可能第一版隻支持在綫聊天;幾個月之後發布第二版,支持離綫消息;又過瞭幾個月,第三版支持隱身聊天;隨後,第四版支持上傳頭像;如此等等。這要求程序員能快速響應新的業務需求,公司纔能保持競爭力。由於業務時常變化(假設每月一次版本升級),也會降低服務程序連續運行時間的要求。相反,我們要設計一套流程,通過輪流重啓服務器來完成平滑升級(§9.2.2)。
  不一定需要遵循公認的通信協議標準 比方說網遊服務器就沒什麼協議標準,反正客戶端和服務端都是本公司開發的,如果發現目前的協議設計有問題,兩邊一起改就行瞭。由於可以自己設計協議,因此我們可以繞開一些性能難點,簡化程序結構。比方說,對於多綫程的服務程序,如果用短連接TCP 協議,為瞭優化性能通常要精心設計accept 新連接的機製2,避免驚群並減少上下文切換。但是如果改用長連接,用最簡單的單綫程accept 就行瞭。
  程序結構沒有定論 對於高並發大吞吐的標準網絡服務,一般采用單綫程事件驅動的方式開發,比如HAProxy、lighttpd 等都是這個模式。但是對於專用的業務係統,其業務邏輯比較復雜,占用較多的CPU 資源,這種單綫程事件驅動方式不見得能發揮現在多核處理器的優勢。這留給程序員比較大的自由發揮空間,做好瞭“橫掃韆軍”,做爛瞭一敗塗地。我認為目前one loop per thread 是通用性較高的一種程序結構,能發揮多核的優勢,見§3.3 和§6.6。
  性能評判的標準不同 如果開發httpd 這樣的通用服務,必然會和開源的Nginx、lighttpd 等高性能服務器比較,程序員要投入相當的精力去優化程序,纔能在市場上占有一席之地。而麵嚮業務的專用網絡程序不一定是Ibound,也不一定有開源的實現以供對比性能,優化方嚮也可能不同。程序員通常更加注重功能的穩定性與開發的便捷性。性能隻要一代比一代強即可。
  網絡編程起到支撐作用,但不處於主導地位 程序員的主要工作是實現業務邏輯,而不隻是實現網絡通信協議。這要求程序員深入理解業務。程序的性能瓶頸不一定在網絡上,瓶頸有可能是CPU、Disk IO、數據庫等,這時優化網絡方麵的代碼並不能提高整體性能。隻有對所在的領域有深入的瞭解,明白各種因素的權衡(trade-off),纔能做齣一些有針對性的優化。現在的機器上,簡單的並發長連接echo服務程序不用特彆優化就做到十多萬qps,但是如果每個業務請求需要1ms 密集計算,在8 核機器上充其量能達到8 000 qps,優化I不如去優化業務計算(如果投入産齣閤算的話)。
  A.1.7 幾個術語
  互聯網上的很多“口水戰”是由對同一術語的不同理解引起的,比如我寫的《多綫程服務器的適用場閤》3,就曾經被人說是“掛羊頭賣狗肉”,因為這篇文章中舉的master 例子“根本就算不上是個網絡服務器。因為它的瓶頸根本就跟網絡無關。”
  網絡服務器 “網絡服務器”這個術語確實含義模糊,到底指硬件還是軟件?到底是服務於網絡本身的機器(交換機、路由器、防火牆、NAT),還是利用網絡為其他人或程序提供服務的機器(打印服務器、文件服務器、郵件服務器)?每個人根據自己熟悉的領域,可能會有不同的解讀。比方說,或許有人認為隻有支持高並發、高吞吐量的纔算是網絡服務器。
  為瞭避免無謂的爭執,我隻用“網絡服務程序”或者“網絡應用程序”這種含義明確的術語。“開發網絡服務程序”通常不會造成誤解。
  客戶端?服務端? 在TCP 網絡編程中,客戶端和服務端很容易區分,主動發起連接的是客戶端,被動接受連接的是服務端。當然,這個“客戶端”本身也可能是個後颱服務程序,HTTP proxy 對HTTP server 來說就是個客戶端。
  客戶端編程?服務端編程? 但是“服務端編程”和“客戶端編程”就不那麼好區分瞭。比如Web crawler,它會主動發起大量連接,扮演的是HTTP 客戶端的角色,但似乎應該歸入“服務端編程”。又比如寫一個HTTP proxy,它既會扮演服務端--被動接受Web browser 發起的連接,也會扮演客戶端--主動嚮HTTP server 發起連接,它究竟算服務端還是客戶端?我猜大多數人會把它歸入服務端編程。
  那麼究竟如何定義“服務端編程”?
  服務端編程需要處理大量並發連接?也許是,也許不是。比如雲風在一篇介紹網遊服務器的博客4 中就談到,網遊中用到的“連接服務器”需要處理大量連接,而“邏輯服務器”隻有一個外部連接。那麼開發這種網遊“邏輯服務器”算服務端編程還是客戶端編程呢?又比如機房的服務進程監控軟件,並發數跟機器數成正比,至多也就是兩三韆的並發連接。(再大規模就超齣本書的範圍瞭。)
  我認為,“服務端網絡編程”指的是編寫沒有用戶界麵的長期運行的網絡程序,程序默默地運行在一颱服務器上,通過網絡與其他程序打交道,而不必和人打交道。與之對應的是客戶端網絡程序,要麼是短時間運行,比如wget;要麼是有用戶界麵(無論是字符界麵還是圖形界麵)。本文主要談服務端網絡編程。
  ……

前言/序言

  本書主要講述采用現代C++ 在x86-64 Linux 上編寫多綫程TCP 網絡服務程序的主流常規技術,這也是我對過去5 年編寫生産環境下的多綫程服務端程序的經驗總結。本書重點講解多綫程網絡服務器的一種IO 模型,即one loop per thread。這是一種適應性較強的模型,也是Linux 下以native 語言編寫用戶態高性能網絡程序最成熟的模式,掌握之後可順利地開發各類常見的服務端網絡應用程序。本書以muduo網絡庫為例,講解這種編程模型的使用方法及注意事項。
  muduo 是一個基於非阻塞IO 和事件驅動的現代C++ 網絡庫,原生支持oneloop per thread 這種IO 模型。muduo 適閤開發Linux 下的麵嚮業務的多綫程服務端網絡應用程序,其中“麵嚮業務的網絡編程”的定義見附錄A。“現代C++”指的不是C++11 新標準,而是2005 年TR1 發布之後的C++ 語言和庫。與傳統C++ 相比,現代C++ 的變化主要有兩方麵:資源管理(見第1 章)與事件迴調(見第449 頁)。
  本書不是多綫程編程教程,也不是網絡編程教程,更不是C++ 教程。讀者應該已經大緻讀過《UNIX 環境高級編程》、《UNIX 網絡編程》、《C++ Primer》或與之內容相近的書籍。本書不談C++11,因為目前(2012 年)主流的Linux 服務端發行版的g++ 版本都還停留在4.4,C++11 進入實用尚需一段時日。
  本書適用的硬件環境是主流x86-64 服務器,多路多核CPU、幾十GB 內存、韆兆以太網互聯。除瞭第5 章講診斷日誌之外,本書不涉及文件IO。
  本書分為四大部分,第1 部分“C++ 多綫程係統編程”考察多綫程下的對象生命期管理、綫程同步方法、多綫程與C++ 的結閤、高效的多綫程日誌等。第2 部分“muduo 網絡庫”介紹使用現成的非阻塞網絡庫編寫網絡應用程序的方法,以及muduo 的設計與實現。第3 部分“工程實踐經驗談”介紹分布式係統的工程化開發方法和C++ 在工程實踐中的功能特性取捨。第4 部分“附錄”分享網絡編程和C++語言的學習經驗。
  本書的宗旨是貴精不貴多。掌握兩種基本的同步原語就可以滿足各種多綫程同步的功能需求,還能寫齣更易用的同步設施。掌握一種進程間通信方式和一種多綫程網絡編程模型就足以應對日常開發任務,編寫運行於公司內網環境的分布式服務係統。(本書不涉及分布式存儲係統,也不涉及UDP。)
  術語與排版範例
  本書大量使用英文術語,甚至有少量英文引文。設計模式的名字一律用英文,例如Observer、Reactor、Singleton。在中文術語不夠突齣時,也會使用英文,例如class、heap、event loop、STL algorithm 等。注意幾個中文C++ 術語: 對象實體(instance)、函數重載決議(resolution)、模闆具現化(instantiation)、覆寫(override)虛函數、提領(dereference)指針。本書中的英語可數名詞一般不用復數形式,例如兩個class,6 個syscall;但有時會用(s) 強調中文名詞是復數。fd 是文件描述符(file descriptor)的縮寫。“CPU 數目”一般指的是核(core)的數目。容量單位kB、MB、GB 錶示的字節數分彆為103、106、109,在特彆強調準確數值時,會分彆用KiB、MiB、GiB 錶示210、220、230 字節。用諸如§11.5 錶示本書第11.5 節,L42 錶示上下文中齣現的第42 行代碼。[JCP]、[CC2e] 等是參考文獻,見書末清單。
  一般術語用普通羅馬字體,如mutex、socket;C++ 關鍵字用無襯綫字體,如class、this、mutable;函數名和class 名用等寬字體,如fork(2)、muduo::EventLoop,其中fork(2) 錶示係統函數fork() 的文檔位於manpage 第2 節,可以通過man 2 fork命令查看。如果函數名或類名過長,可能會摺行,行末有連字號“-”,如EventLoop-ThreadPool。文件路徑和URL 采用窄字體,例如muduo/base/Date.h、http://chenshuo.com。用中文楷體錶示引述彆人的話。
  代碼
  本書的示例代碼以開源項目的形式發布在GitHub 上,地址是
  本書配套頁麵提供全部源代碼打包下載,正文中齣現的類似recipes/thread 的路徑是壓縮包內的相對路徑,讀者不難找到其對應的GitHub URL。本書引用代碼的形式如下,左側數字是文件的行號,右側的“muduo/base/Types.h”是文件路徑1。例如下麵這幾行代碼是muduo::string 的typedef。
  muduo/base/Types.h
  15 namespace muduo
  16 {
  17
  18 #ifdef MUDUO_STD_STRING
  19 using std::string;
  20 #else // !MUDUO_STD_STRING
  21 typedef __gnu_cxx::__sso_string string;
  22 #endif
  muduo/base/Types.h
  在第6、7 兩章的muduo 示例代碼中,路徑muduo/examples/XXX 會簡寫為examples/XXX。此外,第8 章會把recipes/reactor/XXX 簡寫為reactor/XXX。
  本書假定讀者熟悉diff -u 命令的輸齣格式,用於錶示代碼的改動。
  本書正文中齣現的代碼有時為瞭照顧排版而略有改寫,例如改變縮進規則,去掉單行條件語句前後的花括號等。就編程風格而論,應以電子版代碼為準。
  陳碩
  中國·香港


Linux多綫程服務端編程:精煉與實戰 本書並非對特定庫的全麵教程,而是聚焦於現代Linux環境下高性能服務端開發的核心理念、設計模式與實戰技巧。我們將深入剖析多綫程模型在網絡服務中的應用,揭示如何構建穩定、高效、可擴展的服務端程序,為開發者在復雜多變的業務場景中打下堅實的基礎。 核心驅動:理解多綫程的本質與實踐 多綫程是構建高並發服務端的基石,但其復雜性不容忽視。本書將從最基礎的綫程模型齣發,引導讀者理解綫程的創建、同步、通信以及它們對程序性能的影響。我們將深入探討: 綫程生命周期管理: 從創建綫程到綫程的join與detach,掌握綫程的生命周期,確保資源被正確管理,避免內存泄漏和僵屍進程。 同步機製的奧秘: 互斥量(mutex)、條件變量(condition variable)、讀寫鎖(rwlock)等經典同步原語,它們如何協同工作,解決共享數據訪問的衝突,保障程序的正確性。 綫程間通信的藝術: 管道(pipe)、消息隊列(message queue)、共享內存(shared memory)等 IPC(Inter-Process Communication)機製,以及如何巧妙運用它們在多綫程間傳遞信息,實現高效的數據交換。 死鎖與活鎖的規避: 深入分析死鎖和活鎖的成因,掌握多種預防和解決策略,例如鎖的順序化、超時機製、資源預分配等,從根本上避免這些棘手的並發問題。 原子操作與內存模型: 理解C++11及後續標準提供的原子操作,以及底層CPU內存模型對並發編程的影響,編寫真正綫程安全的、高性能的代碼。 設計之道:構建穩健服務的架構思想 成功的服務端程序離不開精妙的設計。本書將引導讀者構建一套適用於高並發場景的設計思維: Reactor與Proactor模型: 深入剖析事件驅動模型,理解Reactor(同步事件分離器)和Proactor(異步事件分離器)的設計思想,它們如何高效地處理大量I/O事件,實現非阻塞I/O。 多綫程模型選擇: 綫程池(Thread Pool)模型、主從(Master-Worker)模型、多進程+多綫程模型等,分析各種模型的優劣勢,以及它們適用的場景,指導讀者根據實際需求選擇最佳模型。 狀態機與有限自動機(FSM): 在處理復雜通信協議或業務邏輯時,狀態機提供瞭一種清晰、可維護的設計方式。本書將展示如何利用狀態機來管理連接狀態、解析協議、處理業務流程。 消息驅動與事件驅動: 強調以消息或事件為核心的設計理念,解耦各個模塊,提升係統的響應速度和可維護性。 模塊化與可擴展性: 構建插件化、易於擴展的係統架構,使得新增功能或修改現有功能不會對整體造成過大的影響。 實戰煉金:核心技術與案例剖析 理論結閤實踐,本書將通過一係列貼近實際的案例,將抽象的概念具象化,讓讀者親手構建齣高性能的服務端應用: 網絡I/O的深度優化: 非阻塞I/O(Non-blocking I/O): 深入理解`epoll`、`kqueue`等高效I/O多路復用技術的原理,以及如何在C++中高效地使用它們。 異步I/O(Asynchronous I/O): 探討AIO在某些場景下的優勢,以及其在Linux下的實現方式。 零拷貝(Zero-copy): 剖析`sendfile`等零拷貝技術的原理,最大化網絡數據傳輸效率,減少CPU開銷。 協議設計與解析: TCP/IP協議棧的理解: 從更深的層次理解TCP/IP協議棧的工作原理,有助於編寫更健壯的網絡程序。 自定義協議的設計: 如何設計高效、靈活的自定義應用層協議,以滿足特定業務需求。 序列化與反序列化: Protobuf、JSON等序列化技術在網絡通信中的應用,以及如何實現高效的數據傳輸。 可靠性與健壯性: 異常處理與錯誤恢復: 建立完善的異常處理機製,確保程序在遇到異常時能夠優雅地退齣或進行自我恢復。 日誌係統的構建: 設計高效、靈活的日誌係統,記錄關鍵信息,便於問題排查和係統監控。 超時與重試機製: 在網絡通信中,超時和重試是必不可少的機製,如何閤理設計這些機製以提高係統的容錯能力。 資源限製與優雅降級: 如何在高負載下控製資源使用,防止服務崩潰,並提供必要的降級服務。 性能調優: 性能瓶頸的定位: 使用性能分析工具(如`perf`、`gprof`)來識彆代碼中的性能瓶頸。 內存優化: 避免內存碎片,減少內存分配次數,優化內存使用模式。 CPU緩存友好性: 理解CPU緩存的工作原理,編寫更具緩存友好性的代碼,提升數據訪問速度。 係統調用優化: 減少不必要的係統調用,批量處理數據。 麵嚮的讀者 本書適閤具備以下背景的開發者: C++基礎紮實: 熟悉C++語法、麵嚮對象編程以及STL。 Linux係統基礎: 瞭解Linux基本命令、文件係統、進程管理等。 網絡編程基礎: 瞭解TCP/IP協議基礎,有socket編程經驗者更佳。 希望提升服務端開發能力: 渴望構建高性能、高並發、高可用服務的開發者。 麵臨技術瓶頸: 在處理並發、性能優化、係統穩定性方麵遇到挑戰的工程師。 學習路徑與收獲 通過本書的學習,您將能夠: 深刻理解多綫程編程的挑戰與機遇。 掌握Linux環境下高效網絡I/O的核心技術。 能夠設計和實現高並發、可擴展的服務端架構。 具備分析和解決復雜服務端問題的能力。 寫齣更健壯、更高效、更具性能的服務端代碼。 本書提供的是一套通用、通用的技術框架與思維模式,適用於各類網絡服務的設計與實現,無論您是開發RPC框架、高性能Web服務器、遊戲服務器、IM係統,還是其他需要高並發處理的網絡應用,本書都將是您不可多得的寶貴財富。我們相信,通過對本書內容的深入學習和實踐,您將能夠站在更高的起點,自信地迎接現代服務端開發的各項挑戰。

用户评价

评分

我最近剛拿到這本《Linux多綫程服務端編程》,雖然還隻是翻閱瞭前幾章,但它所展現齣的紮實功底和清晰思路已經深深吸引瞭我。作者對C++11特性的運用,以及如何將其巧妙地融入到muduo這個網絡庫的設計中,讓我看到瞭現代C++在高性能服務端開發中的巨大潛力。書中對多綫程並發模型,特彆是基於事件驅動和綫程池的結閤,有著深入的探討。我特彆關注書中關於綫程安全、鎖的粒度控製以及如何避免死鎖等關鍵技術點。以往在開發過程中,這些問題常常讓我頭疼不已,而這本書似乎提供瞭一套係統性的解決方案。我相信,隨著閱讀的深入,我將能夠更透徹地理解Linux下高性能網絡服務端的構建原理,並能夠運用muduo庫解決實際開發中的痛點問題。這本書的價值,在於它不僅僅是一本技術手冊,更像是一位經驗豐富的前輩在傳授寶貴的實踐經驗。

评分

拿到《Linux多綫程服務端編程》這本書,我首先被其厚重的篇幅和精美的排版所吸引。從目錄來看,它涵蓋瞭從基礎的網絡協議知識到muduo庫的深入解析,再到多綫程編程的各種實踐技巧,可以說是一個非常全麵的體係。我一直以來都對Linux下的係統編程和網絡編程抱有濃厚的興趣,而muduo庫又是C++網絡編程領域的一個標杆。我希望通過這本書,能夠係統地學習到如何利用muduo構建一個高性能、高可靠性的服務端應用。我尤其期待書中在並發模型、綫程間通信、以及如何處理高並發IO的那些章節,這通常是服務端編程中最具挑戰性的部分。這本書的齣現,對我來說,就像是打開瞭一扇通往更高技術境界的大門,我迫不及待地想去探索其中的奧秘,並將其運用到我的實際工作中,解決那些曾經讓我頭疼的難題。

评分

對於《Linux多綫程服務端編程》這本書,我寄予瞭很高的期望。在當前互聯網技術飛速發展的時代,構建高效、可伸縮、高並發的網絡服務已成為常態。而muduo C++網絡庫,憑藉其在業界良好的口碑,無疑是實現這一目標的重要工具。我預感這本書會非常深入地剖析muduo庫的底層實現,例如其非阻塞IO、事件循環、綫程安全的內存管理等核心概念。我渴望瞭解如何在復雜的網絡環境下,通過muduo來優雅地處理大量的並發連接,如何設計齣健壯的容錯機製,以及如何進行有效的性能調優。這本書不僅僅是關於一個庫的使用,更是關於一種設計思想和工程實踐的傳承。我期待著它能帶領我深入理解高性能服務端編程的藝術,讓我能夠獨立承擔起更具挑戰性的項目,並從中獲得技術上的成長和滿足感。

评分

《Linux多綫程服務端編程》這本書,在我看來,不僅僅是關於muduo C++網絡庫的教學,更是一次關於現代C++在高性能服務端開發領域應用的深度探索。我非常期待書中能夠詳盡地闡述muduo庫的設計哲學,比如它如何巧妙地平衡性能與易用性,如何在高並發場景下保證綫程安全,以及它在異步IO模型上的獨特之處。對於我這樣一個有著多年編程經驗的開發者來說,我更看重的是書中所蘊含的設計思想和工程實踐。我希望通過閱讀這本書,能夠學習到如何從宏觀上把握一個大型網絡服務的設計,如何做齣閤理的架構決策,以及如何在實際開發中避免常見的陷阱。我相信,這本書將為我提供一套係統性的方法論,幫助我構建齣更穩定、更高效、更易於維護的服務端應用。

评分

這本《Linux多綫程服務端編程》圍繞著muduo C++網絡庫展開,雖然我還沒來得及深入閱讀,但僅僅從目錄和作者在技術社區的聲譽來看,它無疑是一本重量級的作品。我一直對高性能網絡編程抱有濃厚的興趣,尤其是如何在高並發場景下設計和實現穩定、高效的服務端,這其中的挑戰和學問是巨大的。muduo庫以其精巧的設計和對C++11新特性的充分利用而聞名,這本書的齣現,勢必會成為我掌握muduo、理解多綫程服務端架構的絕佳跳闆。我期待著書中能夠詳細闡述muduo的Reactor-Handler模型,以及它在多綫程環境下的同步與異步機製。更重要的是,我希望通過這本書,能夠學習到如何將這些理論知識轉化為實際可用的代碼,構建齣真正能夠應對高負載的網絡應用。對於像我這樣希望在服務端開發領域有所突破的開發者來說,這絕對是一本不可多得的參考書,它預示著我將踏上一段充滿挑戰與收獲的學習旅程。

评分

好,看着不错!!!!!!!

评分

不值这个价……………

评分

一直在京东买东西

评分

不错

评分

可以

评分

学习电脑很有用,用券购买划算

评分

正版图书很好。

评分

想通过这本书进一步学习C++

评分

bnhhhhkmjjjjjkk

相关图书

本站所有內容均為互聯網搜索引擎提供的公開搜索信息,本站不存儲任何數據與內容,任何內容與數據均與本站無關,如有需要請聯繫相關搜索引擎包括但不限於百度google,bing,sogou

© 2025 tushu.tinynews.org All Rights Reserved. 求知書站 版权所有