C++ 服務器開發精髓

張遠龍

  • 出版商: 電子工業
  • 出版日期: 2021-06-01
  • 售價: $1,008
  • 貴賓價: 9.5$958
  • 語言: 簡體中文
  • 頁數: 752
  • 裝訂: 平裝
  • ISBN: 7121412632
  • ISBN-13: 9787121412639
  • 相關分類: C++ 程式語言
  • 立即出貨

買這商品的人也買了...

商品描述

本書從操作系統原理角度講解進行C++服務器開發所需掌握的技術棧。全書總計9章,第1~2章講解C++ 11/14/17新標準中的常用特性、新增類庫,以及C++開發者必須熟練掌握的開發調試工具鏈;第3~6章詳細講解C++服務器開發中的多線程編程技術、網絡編程重難點知識、網絡故障調試與排查常用工具,以及通信協議的設計思路、技巧;第7~8章詳細講解一個帶網絡通信組件的高性能服務的基本設計思路和註意事項;第9章進一步補充服務相關的常用模塊設計思路和方法。本書秉承的思想是,通過掌握技術原理,可以輕松製造“輪子”,靈活設計出優雅、魯棒的服務,並快速學習新技術。無論是對於C/C++開發者、電腦專業的學生,還是對於想瞭解操作系統原理的讀者,本書都極具參考價值。

作者簡介

張遠龍,微信公眾號“高性能服務器開發”的作者,曾就職於銀天下、攜程、字節跳動等公司,做過金融交易系統、IM、呼叫中心等項目,研究方向為高性能高並發服務開發。

目錄大綱

第1章C++必知必會.. 1
1.1 C++ RAII慣用法... 1
1.1.1 版本1:最初的寫法... 1
1.1.2 版本2:使用goto語句... 3
1.1.3 版本3:使用do...while(0)循環... 5
1.1.4 版本4:使用RAII慣用法... 7
1.1.5 小結... 12
1.2 pimpl慣用法... 12
1.3 C++ 11/14/17新增的實用特性... 17
1.4 統一的類成員初始化語法與std::initializer_list. 19
1.5 C++ 17註解標籤(attributes)... 24
1.5.1 C++ 98/03的enumeration和C++ 11的enumerator 25
1.5.2 C++ 17的註解標籤... 25
1.6 final、override關鍵字和=default、=delete語法... 28
1.7 auto關鍵字的用法... 34
1.8 Range-based循環語法... 35
1.8.1 自定義對像如何支持Range-based循環語法... 37
1.8.2 for-each循環的實現原理... 38
1.9 C++ 17結構化綁定... 39
1.10 stl容器新增的實用方法... 43
1.10.1 原位構造與容器的emplace系列函數... 43
1.10.2 std::map的try_emplace方法與insert_or_assign方法... 44
1.11 stl 中的智能指針類詳解... 52

第2章C++後端開發必備的工具和調試知識.. 71
2.1 SSH工具與FTP工具... 71
2.1.1 Xshell 71
2.1.2 FTP. 75
2.2 makefile與CMake. 76
2.3 使用Visual Studio管理和閱讀開源項目代碼... 83
2.4 gdb調試... 87
2.4.1 被調試的程序需要帶調試信息... 87
2.4.2 啟動gdb調試的方法... 89
2.5 gdb常用命令詳解——利用gdb調試Redis. 94
2.6 使用gdb調試多線程程序... 126
2.6.1 調試多線程程序的方法... 126
2.6.2 在調試時控制線程切換... 128
2.7 使用gdb調試多進程程序——以調試Nginx為例... 137
2.8 gdb實用調試技巧... 143
2.8.1 將print輸出的字符串或字符數組完整顯示... 144
2.8.2 讓被gdb調試的程序接收信號... 144
2.8.3 函數明明存在,添加斷點時卻無效... 145
2.8.4 調試中的斷點... 146
2.8.5 自定義gdb調試命令... 147
2.9 gdb tui——gdb圖形化界面... 148
2.9.1 開啟gdb TUI模式... 149
2.9.2 gdb TUI模式下的4個窗口... 149
2.9.3 解決tui窗口不自動更新內容的問題... 150
2.9.4 窗口焦點切換... 150
2.10 gdb的升級版——cgdb. 151
2.11 使用VisualGDB調試... 154
2.11.1 使用VisualGDB調試已經運行的程序... 155
2.11.2 使用VisualGDB從頭調試程序... 156

第3章多線程編程與資源同步.. 159
3.1 線程的基本概念及常見問題... 159
3.1.1 主線程退出,支線程也將退出嗎... 159
3.1.2 某個線程崩潰,會導致進程退出嗎... 160
3.2 線程的基本操作... 160
3.3 慣用法:將C++類對象實例指針作為線程函數的參數... 178
3.4 整型變量的原子操作... 184
3.4.1 為什麼給整型變量賦值不是原子操作... 185
3.4.2 Windows平台上對整型變量的原子操作... 186
3.4.3 C++ 11對整型變量原子操作的支持... 187
3.5 Linux線程同步對象... 190
3.5.1 Linux互斥體... 190
3.5.2 Linux信號量... 198
3.5.3 Linux條件變量... 202
3.5.4 Linux讀寫鎖... 208
3.6 Windows線程同步對象... 217
3.6.1 WaitForSingleObject與WaitForMultipleObjects函數... 217
3.6.2 Windows臨界區對象... 219
3.6.3 Windows Event對象... 224
3.6.4 Windows Mutex對象... 229
3.6.5 Windows Semaphore對象... 231
3.6.6 Windows讀寫鎖... 235
3.6.7 Windows條件變量... 238
3.6.8 在多進程之間共享線程同步對象... 243
3.7 C++ 11/14/17線程同步對象... 244
3.7.1 std::mutex系列... 244
3.7.2 std::shared_mutex. 248
3.7.3 std::condition_variable. 253
3.8 如何確保創建的線程一定能運行... 256
3.9 多線程使用鎖經驗總結... 258
3.10 線程局部存儲... 262
3.10.1 Windows的線程局部存儲... 262
3.10.2 Linux的線程局部存儲... 264
3.10.3 C++ 11 的thread_local 關鍵字... 267
3.11 C庫的非線程安全函數... 268
3.12 線程池與隊列系統的設計... 270
3.12.1 線程池的設計原理... 270
3.12.2 環形隊列... 275
3.12.3 消息中間件... 275
3.13 纖程(Fiber)與協程(Routine)... 277

第4章網絡編程重難點解析.. 282
4.1 學習網絡編程時應該掌握的socket函數... 282
4.1.1 在Linux上查看socket函數的幫助信息... 283
4.1.2 在Windows上查看socket函數的幫助信息... 285
4.2 TCP網絡通信的基本流程... 286
4.3 設計跨平台網絡通信庫時的一些socket函數用法... 290
4.3.1 socket數據類型... 290
4.3.2 在Windows上調用socket函數... 290
4.3.3 關閉socket函數... 291
4.3.4 獲取socket函數的錯誤碼... 291
4.3.5 套接字函數的返回值... 293
4.3.6 select函數第1個參數的問題... 293
4.3.7 錯誤碼WSAEWOULDBLOCK和EWOULDBLOCK.. 294
4.4 bind函數重難點分析... 294
4.4.1 對bind函數如何選擇綁定地址... 294
4.4.2 bind函數的端口號問題... 295
4.5 select函數的用法和原理... 302
4.5.1 Linux上的select函數... 302
4.5.2 Windows上的select函數... 317
4.6 socket的阻塞模式和非阻塞模式... 318
4.6.1 如何將socket設置為非阻塞模式... 318
4.6.2 send和recv函數在阻塞和非阻塞模式下的表現... 320
4.6.3 非阻塞模式下send和recv函數的返回值總結... 331
4.6.4 阻塞與非阻塞socket的各自適用場景... 333
4.7 發送0字節數據的效果... 333
4.8 connect函數在阻塞和非阻塞模式下的行為... 339
4.9 連接時順便接收第1組數據... 343
4.10 如何獲取當前socket對應的接收緩衝區中的可讀數據量... 346
4.11 Linux EINTR錯誤碼... 351
4.12 Linux SIGPIPE信號... 352
4.13 Linux poll 函數的用法... 353
4.14 Linux epoll模型... 361
4.14.1 基本用法... 361
4.14.2 epoll_wait與poll函數的區別... 363
4.14.3 LT 模式和ET 模式... 363
4.14.4 EPOLLONESHOT 選項... 380
4.15 高效的readv和writev函數... 386
4.16 主機字節序和網絡字節序... 387
4.16.1 主機字節序... 387
4.16.2 網絡字節序... 388
4.16.3 操作系統提供的字節轉換函數匯總... 389
4.17 域名解析API介紹... 390

第5章網絡通信故障排查常用命令.. 397
5.1 ifconfig命令... 397
5.2 ping命令... 401
5.3 telnet命令... 402
5.4 netstat命令... 407
5.5 lsof命令... 409
5.6 nc命令... 412
5.7 curl命令... 415
5.8 tcpdump命令... 416

第6章網絡通信協議設計.. 422
6.1 理解TCP. 422
6.2 如何解決粘包問題... 423
6.3 解包與處理... 425
6.4 從struct到TLV.. 430
6.4.1 協議的演化... 430
6.4.2 協議的分類... 434
6.4.3 協議設計工具... 434
6.5 整型數值的壓縮... 435
6.6 設計通信協議時的注意事項... 437
6.6.1 字節對齊... 437
6.6.2 顯式地指定整型字段的長度... 438
6.6.3 涉及浮點數時要考慮精度問題... 438
6.6.4 大小端問題... 438
6.6.5 協議與自動升級功能
6.7 包分片... 439
6.8 XML與JSON格式的協議... 444
6.9 一個自定義協議示例... 445
6.10 理解HTTP. 460
6.10.1 HTTP格式介紹... 460
6.10.2 GET與POST方法... 461
6.10.3 HTTP chunk編碼... 465
6.10.4 HTTP客戶端的編碼實現... 466
6.10.5 HTTP服務端的實現... 466
6.10.6 HTTP與長連接... 471
6.10.7 libcurl 471
6.10.8 Restful接口與Java Spring MVC.. 477
6.11 SMTP、POP3與郵件客戶端... 478
6.12 WebSocket協議... 499
6.12.1 WebSocket協議的握手過程... 500
6.12.2 WebSocket協議的格式... 503
6.12.3 WebSocket協議的壓縮格式... 506
6.12.4 WebSocket協議裝包與解包示例... 508
6.12.5 解析握手協議... 512

第7章單個服務的基本結構.. 515
7.1 網絡通信組件的效率問題... 515
7.1.1 高效網絡通信框架的設計原則... 515
7.1.2 連接的被動關閉與主動關閉... 519
7.1.3 長連接和短連接... 519
7.2 原始的服務器結構... 520
7.3 一個連接對應一個線程模型... 522
7.4 Reactor模式... 523
7.5 one thread one loop思想... 524
7.5.1 one thread one loop程序的基本結構... 524
7.5.2 線程的分工... 525
7.5.3 喚醒機制的實現... 527
7.5.4 handle_other_things方法的實現邏輯... 532
7.5.5 帶定時器的程序結構... 533
7.5.6 one thread one loop的效率保障... 534
7.6 收發數據的正確做法... 534
7.6.1 如何收取數據... 534
7.6.2 如何發送數據... 535
7.6.3 不要多個線程同時利用一個socket收(發)數據... 538
7.7 發送、接收緩衝區的設計要點... 538
7.7.1 為什麼需要發送緩衝區和接收緩衝區... 539
7.7.2 如何設計發送緩衝區和接收緩衝區... 539
7.7.3 服務端發送數據時對端一直不接收的問題... 543
7.8 網絡庫的分層設計... 544
7.8.1 網絡庫設計中的各個層... 544
7.8.2 將Session進一步分層... 550
7.8.3 連接信息與EventLoop/Thread的對應關係... 551
7.9 後端服務中的定時器設計... 551
7.9.1 最簡單的定時器... 551
7.9.2 定時器設計的基本思路... 552
7.9.3 定時器邏輯的性能優化... 561
7.9.4 對時間的緩存... 564
7.10 處理業務數據時是否一定要單獨開線程... 565
7.11 非侵入式結構與侵入式結構... 570
7.11.1 非侵入式結構... 570
7.11.2 侵入式結構... 571
7.12 帶有網絡通信模塊的服務器的經典結構... 578
7.12.1 為何要將listenfd設置成非阻塞模式... 578
7.12.2 基於one thread one loop結構的經典服務器結構... 584
7.12.3 服務器的性能瓶頸... 586

第8章Redis網絡通信模塊源碼分析.. 587
8.1 調試Redis環境與準備... 587
8.1.1 Redis源碼編譯與啟動... 587
8.1.2 通信示例與術語約定... 589
8.2 探究redis-server端的網絡通信模塊... 589
8.3 探究redis-cli端的網絡通信模型... 663
8.4 Redis的通信協議格式... 673
8.4.1 請求命令格式... 673
8.4.2 應答命令格式... 674
8.4.3 多命令和流水線... 677
8.4.4 特殊的redis-cli與內聯命令... 677
8.4.5 Redis對協議數據的解析邏輯... 678

第9章服務器開發中的常用模塊設計.. 681
9.1 斷線自動重連的應用場景和邏輯設計... 681
9.2 保活機制與心跳包... 683
9.2.1 TCP keepalive選項... 683
9.2.2 應用層的心跳包機制設計... 684
9.2.3 有代理的心跳包機制設計... 689
9.2.4 帶業務數據的心跳包... 690
9.2.5 心跳包與流量... 690
9.2.6 心跳包與調試... 691
9.2.7 心跳包與日誌... 691
9.3 日誌模塊的設計... 692
9.4 錯誤碼系統的設計... 730
9.4.1 錯誤碼的作用... 730
9.4.2 錯誤碼系統設計實踐... 731
9.5 監控端口... 733