展开全部

主编推荐语

本书从操作系统原理角度讲解了进行C服务器开发所需掌握的技术栈。

内容简介

全书总计9章,第1~2章讲解C11/14/17新标准中的常用特性、新增类库,以及C开发者必须熟练掌握的开发调试工具链;第3~6章详细讲解C服务器开发中的多线程编程技术、网络编程重难点知识、网络故障调试与排查常用工具,以及通信协议的设计思路、技巧;第7~8章详细讲解一个带网络通信组件的高性能服务的基本设计思路和注意事项;第9章进一步补充服务相关的常用模块设计思路和方法。

本书秉承的思想是,通过掌握技术原理,可以轻松制造“轮子”,灵活设计出优雅、鲁棒的服务,并快速学习新技术。无论是对于C/C开发者、计算机专业的学生,还是对于想了解操作系统原理的读者,本书都极具参考价值。

目录

  • 版权信息
  • 内容简介
  • 前言
  • 第1章 C++必知必会
  • 1.1 C++RAII惯用法
  • 1.1.1 版本1:最初的写法
  • 1.1.2 版本2:使用goto语句
  • 1.1.3 版本3:使用do...while(0)循环
  • 1.1.4 版本4:使用RAII惯用法
  • 1.1.5 小结
  • 1.2 pimpl惯用法
  • 1.3 C++11/14/17新增的实用特性
  • 1.4 统一的类成员初始化语法与std::initializer_list<T>
  • 1.5 C++17注解标签(attributes)
  • 1.5.1 C++98/03的enumeration和C++11的enumerator
  • 1.5.2 C++17的注解标签
  • 1.6 final、override关键字和=default、=delete语法
  • 1.6.1 final关键字
  • 1.6.2 override关键字
  • 1.6.3 =default语法
  • 1.6.4 =delete语法
  • 1.7 auto关键字的用法
  • 1.8 Range-based循环语法
  • 1.8.1 自定义对象如何支持Range-based循环语法
  • 1.8.2 for-each循环的实现原理
  • 1.9 C++17结构化绑定
  • 1.10 stl容器新增的实用方法
  • 1.10.1 原位构造与容器的emplace系列函数
  • 1.10.2 std::map的try_emplace方法与insert_or_assign方法
  • 1.11 stl中的智能指针类详解
  • 1.11.1 C++98/03的尝试——std::auto_ptr
  • 1.11.2 std::unique_ptr
  • 1.11.3 std::shared_ptr
  • 1.11.4 std::enable_shared_from_this
  • 1.11.5 std::weak_ptr
  • 1.11.6 智能指针对象的大小
  • 1.11.7 使用智能指针时的注意事项
  • 第2章 C++后端开发必备的工具和调试知识
  • 2.1 SSH工具与FTP工具
  • 2.1.1 Xshell
  • 2.1.2 FTP
  • 2.2 makefile与CMake
  • 2.3 使用Visual Studio管理和阅读开源项目代码
  • 2.4 gdb调试
  • 2.4.1 被调试的程序需要带调试信息
  • 2.4.2 启动gdb调试的方法
  • 2.5 gdb常用命令详解
  • 2.5.1 gdb常用调试命令概览和说明
  • 2.5.2 用gdb调试Redis前的准备工作
  • 2.5.3 run命令
  • 2.5.4 continue命令
  • 2.5.5 break命令
  • 2.5.6 tbreak命令
  • 2.5.7 backtrace与frame命令
  • 2.5.8 info break、enable、disable、delete命令
  • 2.5.9 list命令
  • 2.5.10 print与ptype命令
  • 2.5.11 info与thread命令
  • 2.5.12 next、step、until、finish、return、jump命令
  • 2.5.13 disassemble命令
  • 2.5.14 set args与show args命令
  • 2.5.15 watch命令
  • 2.5.16 display命令
  • 2.5.17 dir命令
  • 2.6 使用gdb调试多线程程序
  • 2.6.1 调试多线程程序的方法
  • 2.6.2 在调试时控制线程切换
  • 2.7 使用gdb调试多进程程序
  • 2.8 gdb实用调试技巧
  • 2.8.1 将print输出的字符串或字符数组完整显示
  • 2.8.2 让被gdb调试的程序接收信号
  • 2.8.3 函数明明存在,添加断点时却无效
  • 2.8.4 调试中的断点
  • 2.8.5 自定义gdb调试命令
  • 2.9 gdb tui
  • 2.9.1 开启gdb TUI模式
  • 2.9.2 gdb TUI模式下的4个窗口
  • 2.9.3 解决tui窗口不自动更新内容的问题
  • 2.9.4 窗口焦点切换
  • 2.10 gdb的升级版
  • 2.11 使用VisualGDB调试
  • 2.11.1 使用VisualGDB调试已经运行的程序
  • 2.11.2 使用VisualGDB从头调试程序
  • 第3章 多线程编程与资源同步
  • 3.1 线程的基本概念及常见问题
  • 3.1.1 主线程退出,支线程也将退出吗
  • 3.1.2 某个线程崩溃,会导致进程退出吗
  • 3.2 线程的基本操作
  • 3.2.1 创建线程
  • 3.2.2 获取线程ID
  • 3.2.3 等待线程结束
  • 3.3 惯用法:将C++类对象实例指针作为线程函数的参数
  • 3.4 整型变量的原子操作
  • 3.4.1 为什么给整型变量赋值不是原子操作
  • 3.4.2 Windows平台上对整型变量的原子操作
  • 3.4.3 C++11对整型变量原子操作的支持
  • 3.5 Linux线程同步对象
  • 3.5.1 Linux互斥体
  • 3.5.2 Linux信号量
  • 3.5.3 Linux条件变量
  • 3.5.4 Linux读写锁
  • 3.6 Windows线程同步对象
  • 3.6.1 WaitForSingleObject与WaitForMultipleObjects函数
  • 3.6.2 Windows临界区对象
  • 3.6.3 Windows Event对象
  • 3.6.4 Windows Mutex对象
  • 3.6.5 Windows Semaphore对象
  • 3.6.6 Windows读写锁
  • 3.6.7 Windows条件变量
  • 3.6.8 在多进程之间共享线程同步对象
  • 3.7 C++11/14/17线程同步对象
  • 3.7.1 std::mutex系列
  • 3.7.2 std::shared_mutex
  • 3.7.3 std::condition_variable
  • 3.8 如何确保创建的线程一定能运行
  • 3.9 多线程使用锁经验总结
  • 3.9.1 减少锁的使用次数
  • 3.9.2 明确锁的范围
  • 3.9.3 减少锁的使用粒度
  • 3.9.4 避免死锁的一些建议
  • 3.9.5 避免活锁的一些建议
  • 3.10 线程局部存储
  • 3.10.1 Windows的线程局部存储
  • 3.10.2 Linux的线程局部存储
  • 3.10.3 C++11的thread_local关键字
  • 3.11 C库的非线程安全函数
  • 3.12 线程池与队列系统的设计
  • 3.12.1 线程池的设计原理
  • 3.12.2 环形队列
  • 3.12.3 消息中间件
  • 3.13 纤程(Fiber)与协程(Routine)
  • 3.13.1 纤程
  • 3.13.2 协程
  • 第4章 网络编程重难点解析
  • 4.1 学习网络编程时应该掌握的socket函数
  • 4.1.1 在Linux上查看socket函数的帮助信息
  • 4.1.2 在Windows上查看socket函数的帮助信息
  • 4.2 TCP网络通信的基本流程
  • 4.3 设计跨平台网络通信库时的一些socket函数用法
  • 4.3.1 socket数据类型
  • 4.3.2 在Windows上调用socket函数
  • 4.3.3 关闭socket函数
  • 4.3.4 获取socket函数的错误码
  • 4.3.5 套接字函数的返回值
  • 4.3.6 select函数第1个参数的问题
  • 4.3.7 错误码WSAEWOULDBLOCK和EWOULDBLOCK
  • 4.4 bind函数重难点分析
  • 4.4.1 对bind函数如何选择绑定地址
  • 4.4.2 bind函数的端口号问题
  • 4.5 select函数的用法和原理
  • 4.5.1 Linux上的select函数
  • 4.5.2 Windows上的select函数
  • 4.6 socket的阻塞模式和非阻塞模式
  • 4.6.1 如何将socket设置为非阻塞模式
  • 4.6.2 send和recv函数在阻塞和非阻塞模式下的表现
  • 4.6.3 非阻塞模式下send和recv函数的返回值总结
  • 4.6.4 阻塞与非阻塞socket的各自适用场景
  • 4.7 发送0字节数据的效果
  • 4.8 connect函数在阻塞和非阻塞模式下的行为
  • 4.9 连接时顺便接收第1组数据
  • 4.10 如何获取当前socket对应的接收缓冲区中的可读数据量
  • 4.10.1 分析
  • 4.10.2 注意事项
  • 4.11 Linux EINTR错误码
  • 4.12 Linux SIGPIPE信号
  • 4.13 Linux poll函数的用法
  • 4.14 Linux epoll模型
  • 4.14.1 基本用法
  • 4.14.2 epoll_wait与poll函数的区别
  • 4.14.3 LT模式和ET模式
  • 4.14.4 EPOLLONESHOT选项
  • 4.15 高效的readv和writev函数
  • 4.16 主机字节序和网络字节序
  • 4.16.1 主机字节序
  • 4.16.2 网络字节序
  • 4.16.3 操作系统提供的字节转换函数汇总
  • 4.17 域名解析API介绍
  • 第5章 网络通信故障排查常用命令
  • 5.1 ifconfig命令
  • 5.2 ping命令
  • 5.3 telnet命令
  • 5.4 netstat命令
  • 5.5 lsof命令
  • 5.6 nc命令
  • 5.7 curl命令
  • 5.8 tcpdump命令
  • 第6章 网络通信协议设计
  • 6.1 理解TCP
  • 6.2 如何解决粘包问题
  • 6.3 解包与处理
  • 6.4 从struct到TLV
  • 6.4.1 协议的演化
  • 6.4.2 协议的分类
  • 6.4.3 协议设计工具
  • 6.5 整型数值的压缩
  • 6.6 设计通信协议时的注意事项
  • 6.6.1 字节对齐
  • 6.6.2 显式地指定整型字段的长度
  • 6.6.3 涉及浮点数时要考虑精度问题
  • 6.6.4 大小端问题
  • 6.6.5 协议与自动升级功能
  • 6.7 包分片
  • 6.8 XML与JSON格式的协议
  • 6.9 一个自定义协议示例
  • 6.10 理解HTTP
  • 6.10.1 HTTP格式介绍
  • 6.10.2 GET与POST方法
  • 6.10.3 HTTP chunk编码
  • 6.10.4 HTTP客户端的编码实现
  • 6.10.5 HTTP服务端的实现
  • 6.10.6 HTTP与长连接
  • 6.10.7 libcurl
  • 6.10.8 Restful接口与Java Spring MVC
  • 6.11 SMTP、POP3与邮件客户端
  • 6.11.1 邮件协议简介
  • 6.11.2 SMTP
  • 6.11.3 POP3
  • 6.11.4 邮件客户端
  • 6.12 WebSocket协议
  • 6.12.1 WebSocket协议的握手过程
  • 6.12.2 WebSocket协议的格式
  • 6.12.3 WebSocket协议的压缩格式
  • 6.12.4 WebSocket协议装包与解包示例
  • 6.12.5 解析握手协议
  • 第7章 单个服务的基本结构
  • 7.1 网络通信组件的效率问题
  • 7.1.1 高效网络通信框架的设计原则
  • 7.1.2 连接的被动关闭与主动关闭
  • 7.1.3 长连接和短连接
  • 7.2 原始的服务器结构
  • 7.3 一个连接对应一个线程模型
  • 7.4 Reactor模式
  • 7.5 one thread one loop思想
  • 7.5.1 one thread one loop程序的基本结构
  • 7.5.2 线程的分工
  • 7.5.3 唤醒机制的实现
  • 7.5.4 handle_other_things方法的实现逻辑
  • 7.5.5 带定时器的程序结构
  • 7.5.6 one thread one loop的效率保障
  • 7.6 收发数据的正确做法
  • 7.6.1 如何收取数据
  • 7.6.2 如何发送数据
  • 7.6.3 不要多个线程同时利用一个socket收(发)数据
  • 7.7 发送、接收缓冲区的设计要点
  • 7.7.1 为什么需要发送缓冲区和接收缓冲区
  • 7.7.2 如何设计发送缓冲区和接收缓冲区
  • 7.7.3 服务端发送数据时对端一直不接收的问题
  • 7.8 网络库的分层设计
  • 7.8.1 网络库设计中的各个层
  • 7.8.2 将Session进一步分层
  • 7.8.3 连接信息与EventLoop/Thread的对应关系
  • 7.9 后端服务中的定时器设计
  • 7.9.1 最简单的定时器
  • 7.9.2 定时器设计的基本思路
  • 7.9.3 定时器逻辑的性能优化
  • 7.9.4 对时间的缓存
  • 7.10 处理业务数据时是否一定要单独开线程
  • 7.11 非侵入式结构与侵入式结构
  • 7.11.1 非侵入式结构
  • 7.11.2 侵入式结构
  • 7.12 带有网络通信模块的服务器的经典结构
  • 7.12.1 为何要将listenfd设置成非阻塞模式
  • 7.12.2 基于one thread one loop结构的经典服务器结构
  • 7.12.3 服务器的性能瓶颈
  • 第8章 Redis网络通信模块源码分析
  • 8.1 调试Redis环境与准备
  • 8.1.1 Redis源码编译与启动
  • 8.1.2 通信示例与术语约定
  • 8.2 探究redis-schmerver端的网络通信模块
  • 8.2.1 监听fd的初始化工作
  • 8.2.2 接受客户端连接
  • 8.2.3 epollfd的创建
  • 8.2.4 监听fd与客户端fd是如何挂载到epollfd上的
  • 8.2.5 readQueryFromClient函数
  • 8.2.6 如何处理可写事件
  • 8.2.7 Redis 6.0多线程网络I/O
  • 8.2.8 Redis对客户端的管理
  • 8.2.9 客户端断开流程
  • 8.2.10 Redis中收发缓冲区的设计
  • 8.2.11 定时器逻辑
  • 8.2.12 钩子函数
  • 8.2.13 redis-schmerver端网络通信模块小结
  • 8.3 探究redis-cli端的网络通信模型
  • 8.4 Redis的通信协议格式
  • 8.4.1 请求命令格式
  • 8.4.2 应答命令格式
  • 8.4.3 多命令和流水线
  • 8.4.4 特殊的redis-cli与内联命令
  • 8.4.5 Redis对协议数据的解析逻辑
  • 第9章 服务器开发中的常用模块设计
  • 9.1 断线自动重连的应用场景和逻辑设计
  • 9.2 保活机制与心跳包
  • 9.2.1 TCP keepalive选项
  • 9.2.2 应用层的心跳包机制设计
  • 9.2.3 有代理的心跳包机制设计
  • 9.2.4 带业务数据的心跳包
  • 9.2.5 心跳包与流量
  • 9.2.6 心跳包与调试
  • 9.2.7 心跳包与日志
  • 9.3 日志模块的设计
  • 9.3.1 为什么需要日志
  • 9.3.2 日志系统的技术实现
  • 9.3.3 在C/C++中输出网络数据包日志
  • 9.3.4 调试时的日志
  • 9.3.5 统计程序性能日志
  • 9.3.6 根据类型将日志写入不同的文件中
  • 9.3.7 集中式日志服务与分布式日志服务
  • 9.3.8 从业务层面看在一条日志中应该包含什么内容
  • 9.3.9 在日志中不要出现敏感信息
  • 9.3.10 开发过程中的日志递进缩减策略
  • 9.4 错误码系统的设计
  • 9.4.1 错误码的作用
  • 9.4.2 错误码系统设计实践
  • 9.5 监控端口
展开全部

评分及书评

5.0
4个评分

出版方

电子工业出版社

电子工业出版社成立于1982年10月,是国务院独资、工信部直属的中央级科技与教育出版社,是专业的信息技术知识集成和服务提供商。经过三十多年的建设与发展,已成为一家以科技和教育出版、期刊、网络、行业支撑服务、数字出版、软件研发、软科学研究、职业培训和教育为核心业务的现代知识服务集团。出版物内容涵盖了电子信息技术的各个分支及工业技术、经济管理、科普与少儿、社科人文等领域,综合出版能力位居全国出版行业前列。