Linux:Web和I/O系列书籍读书笔记
目录
本读书笔记记录和Linux环境下,Web开发,I/O模型相关的所有书籍。
参考书籍列表
书籍名称 | C++版本 | 重点 |
---|---|---|
Linux多线程服务端编程:使用muduo C++网络库 | 早于C++11 | 线程安全 |
Linux高性能服务器编程 | TCP/IP和IO模型 | |
C++服务器开发精髓 |
术语
- RTT:Round-Trip Time 往返时延。数据包发送和接收ACK确认的时间差。
- RTO:Retransmission Timeout 超时重传时间。
工具和指令
在网络程序开发过程中,有一些指令和工具很有帮助,这里列举一下
名称 | 类型 | 作用 | 常用方法 |
---|---|---|---|
wireshark | 工具软件 | 抓包 | 图形化方式 |
tcpdump | 指令 | 抓包工具 | 对不同协议、网卡、地址等进行筛选的抓包 |
ifstat | 指令 | 网络流量检测 | 主要用于对流量的总体统计,如速率,总量 |
lsof | 指令(list of open file) | 列出当前系统打开的文件描述符 | 一样也可以指定协议、地址、服务名等等 |
nc | 指令(netcat) | 作为服务器或者客户端,构建网络连接 | -l -C等 |
strace | 指令 | 跟踪程序运行过程中的系统调用和接收到的信号 | 相比于gdb调试,strace能更直观的看到运行时的一些信息 |
netstat | 指令 | 查看网络信息统计 | -ntlp 显示地址,仅tcp在监听套接字,显示pid, |
vmstat | 指令 | 查看进程信息、内存使用、CPU使用、I/O使用 | 设置采样频率和内容,磁盘和CPU也可以分别改用iostat/mpstat |
route | 指令 | 查看路由表 | Flags注意,U活跃、G网关、H主机、DM重定向 |
协议栈快速复习
IP
作为网络层协议,IP协议提供无连接、不可靠、无状态的服务。它的核心任务是进行数据报的路由,即决定将数据发送的目标机器所需的路径。下图可以从右向左去看。
对于一台机器来说,接收到IP数据报之后,根据数据报中选择的路由机制,为其进行路由选择。同时也考虑是否是到本机,以及本机是否允许转发IP数据报。对于一个路由来说,允许数据报转发,它需要做一系列事情:
- 检查TTL(TimeToLive,存活时间),如果已经是0,则丢弃
- 检查源路由选择(IP协议可以基于源地址,选择自己的路由策略)。并根据该选项的需要,反馈ICMP报文,通知选站失败或者重定向。
- TTL值减一,做其他的IP头部选项处理
- 如果有必要,进行IP分片
- 转发
而IPV6作为下一代网络层协议,提供了很多扩展。最重要的是增加了多播和流的功能,以及提供了更简洁的固定头部,以及可选的扩展头部。
IPv6协议并不是IPv4 协议的简单扩展,而是完全独立的协议。用以太网封装的IPv6数据报和IPv4数据报,在以太网帧格式中,具有不同的类型值。
TCP
上图是TCP协议格式,其中值得注意的是选项中的字段。这个字段的格式都是:kind、长度、内容。其中长度和内容根据选项而定。对这7种情况有一个印象即可:选项表结束标记、空操作、最大报文段选项、(滑动窗口)窗口扩大因子、选择性确认(用于SACK技术,提高重传性能)、时间戳选项(用于回路时间RTT计算)
带外数据(Out of band),指那些需要迅速通知对端的数据。TCP通过紧急URG状态和紧急指针来完成这种要求。
TCP最重要的特性之一就是提供可靠服务。而这一点是通过超时重传机制做到的。每一个报文段,都有一个定时器,用来查看是否被ACK确认。每一次重传的间隔时间都加倍(和超时重连一样)。在重试失败若干次后,由更底层的网络层协议接管(尝试重新查询网络IP等),直到放弃连接。重试次数和放弃连接前的尝试,都是可以配置的。Linux内核在网络协议栈上提供了相当多的可配置内容。
此外TCP还要考虑拥塞控制:慢启动(指数1/2/4/8增长)、拥塞避免(线性)、快重传/快恢复(连续三个重复ACK)。拥塞控制算法有多种实现。这些算法主要控制/使用了一些变量。
- SWND发送窗口:收到第一个确认之前,可以一次连续写入网络的数据量。用于平衡网络延迟和网络拥塞
- RWND接收窗口:接收方的可用于接收的窗口长度
- CWND拥塞窗口:真正用于控制发送速率的变量。是通过前一轮的CWND和SWND,在每一轮重新计算。如果发生快重传快恢复,则减少到ssthresh
- SMSS:发送端最大报文长度(未确认的全部数据长度),一般等于MSS
- MSS:最大报文长度
- ssthresh:慢启动阈值
socket编程
是Linux的网络编程的抽象。由于从传输层及往下,都是由内核实现的。因此内核向上提供的系统调用,即socket编程,需要提供一组接口,满足
- 将应用程序数据从用户缓冲区中复制到 TCP/UDP内核发送缓冲区,以交付内核来发送数据,或者是从内核TCP/UDP接收缓冲区中复制数据到用户缓冲区,以读取数据
- 应用程序可以通过它们来修改内核中各层协议的某些头部信息或其他数据结构,从而精细地控制底层通信的行为。
- 不仅可以访问TCP/IP协议栈,也可以访问其他网络协议栈。例如UNIX本地域协议栈。