计算机网络笔记
计算机网络笔记
OSI 七层模型
OSI七层模型 |
---|
应用层 |
表示层 |
会话层 |
传输层 |
网络层 |
数据链路层 |
物理层 |
各层功能:
-
应用层
很简单,就是应用程序。这一层负责确定通信对象,并确保由足够的资源用于通信,这些当然都是想要通信的应用程序干的事情。为操作系统或网络应用程序提供访问网络服务的接口。
-
表示层
负责数据的编码、转化,确保应用层的正常工作。这一层,是将我们看到的界面与二进制间互相转化的地方,就是我们的语言与机器语言间的转化。数据的压缩、解压,加密、解密都发生在这一层。这一层根据不同的应用目的将数据处理为不同的格式,表现出来就是我们看到的各种各样的文件扩展名。
-
会话层
负责建立、维护、控制会话,区分不同的会话,以及提供单工(Simplex)、半双工(Half duplex)、全双工(Full duplex)三种通信模式的服务。我们平时所知的NFS,RPC,X Windows等都工作在这一层。管理主机之间的会话进程,即负责建立、管理、终止进程之间的会话。会话层还利用在数据中插入校验点来实现数据的同步。
-
传输层
负责分割、组合数据,实现端到端的逻辑连接。数据在上三层是整体的,到了这一层开始被分割,这一层分割后的数据被称为段(Segment)。三次握手(Three-way handshake),面向连接(Connection-Oriented)或非面向连接(Connectionless-Oriented)的服务,流控(Flow control)等都发生在这一层。是第一个端到端,即主机到主机的层次。传输层负责将上层数据分段并提供端到端的、可靠的或不可靠的传输。此外,传输层还要处理端到端的差错控制和流量控制问题。
- 在这一层,数据的单位称为数据段(segment)。
-
网络层
负责管理网络地址,定位设备,决定路由。我们所熟知的IP地址和路由器就是工作在这一层。上层的数据段在这一层被分割,封装后叫做包(Packet),包有两种,一种叫做用户数据包(Data packets),是上层传下来的用户数据;另一种叫路由更新包(Route update packets),是直接由路由器发出来的,用来和其他路由器进行路由信息的交换。负责对子网间的数据包进行路由选择。网络层还可以实现拥塞控制、网际互连等功能。
- 在这一层,数据的单位称为数据包(packet)。
-
数据链路层
负责准备物理传输,CRC校验,错误通知,网络拓扑,流控等。MAC地址和交换机都工作在这一层。上层传下来的包在这一层被分割封装后叫做帧(Frame)。在不可靠的物理介质上提供可靠的传输。该层的作用
- 包括:物理地址寻址、数据的成帧、流量控制、数据的检错、重发等。
- 在这一层,数据的单位称为帧(frame)。
-
物理层
就是实实在在的物理链路,负责将数据以比特流的方式发送、接收。
各层典型设备:
应用层 ……………… 计算机:应用程序,如FTP,SMTP,HTTP
表示层 ……………… 计算机:编码方式,图像编解码、URL字段传输编码
会话层 ……………… 计算机:建立会话,SESSION认证、断点续传
传输层 ……………… 计算机:进程和端口
网络层………………… 网络:路由器,防火墙、多层交换机
数据链路层 ………… 网络:网卡,网桥,交换机
物理层………………… 网络:中继器,集线器、网线、HUB
各层常见协议
- 应用层 文件传输,电子邮件,文件服务,虚拟终端 HTTP,TFTP,SNMP,FTP,SMTP,DNS,Telnet
- 表示层 数据格式化,代码转换,数据加密 没有协议
- 会话层 解除或建立与别的接点的联系 没有协议
- 传输层 提供端对端的接口 TCP,UDP
- 网络层 为数据包选择路由 IP,ICMP,IGMP,RIP,OSPF,BGP
- 数据链路层 传输有地址的帧以及错误检测功能 ARP,RARP,SLIP,CSLIP,PPP,MTU
- 物理层 以二进制数据形式在物理媒体上传输数据 ISO2110,IEEE802,IEEE802.2
TCP/IP协议
TCP报文
* 源端口和目的端口:各16位;
* 序号和确认号:以字节为单位编号,各32位;
* TCP 每次发送的报文段的首部中的序号字段数值表示该报文段第一个字节的序号。
* TCP 确认号表示接收端期望下次收到的数据中的第一个数据字节的序号。
* TCP头的长度:4位,长度单位为32位字;
* 6位的保留域;
* 6位的标识位:置1表示有效
URG:和紧急指针配合使用,发送紧急数据;
ACK:确认号是否有效;
PSH:指示发送方和接收方将数据不做缓存,立刻发送或接收;
RST:由于不可恢复的错误重置连接;
SYN:用于连接建立指示;
FIN:用于连接释放指示
* 窗口大小:用于基于可变滑动窗口的流控,指示发送方从确认号开始可以再发送窗口大小的字节流;
* 校验和:为增加可靠性,对TCP头,数据和伪头计算校验和;
* 选项字段 —— 长度可变。TCP 最初只规定了一种选项,即最大报文段长度 MSS。MSS 告诉对方 TCP:“我的缓存所能接收的报文段的数据字段的最大长度是 MSS 个字节。”
三次握手与四次挥手
三次握手(我要和你建立链接,你真的要和我建立链接么,我真的要和你建立链接,成功):
第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
四次挥手(我要和你断开链接;好的,我知道了。我数据发完了,断开连接把;好的,断吧):
第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。此时TCP链接处于半关闭状态,即客户端已经没有要发送的数据了,但服务端若发送数据,则客户端仍要接收。
第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
TCP协议如何来保证传输的可靠性
TCP提供一种面向连接的、可靠的字节流服务。其中,面向连接意味着两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须先建立一个TCP连接。在一个TCP连接中,仅有两方进行彼此通信;而字节流服务意味着两个应用程序通过TCP链接交换8bit字节构成的字节流,TCP不在字节流中插入记录标识符。
对于可靠性,TCP通过以下方式进行保证:
数据包校验:目的是检测数据在传输过程中的任何变化,若校验出包有错,则丢弃报文段并且不给出响应,这时TCP发送数据端超时后会重发数据;
对失序数据包重排序:既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。TCP将对失序数据进行重新排序,然后才交给应用层;
丢弃重复数据:对于重复数据,能够丢弃重复数据;
应答机制:当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒;
超时重发:当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段;
流量控制:TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据,这可以防止较快主机致使较慢主机的缓冲区溢出,这就是流量控制。TCP使用的流量控制协议是可变大小的滑动窗口协议。
流量控制
流量控制主要通过滑动窗口机制实现
滑动窗口协议的基本原理就是在任意时刻,发送方都维持了一个连续的允许发送的帧的序号,称为发送窗口;同时,接收方也维持了一个连续的允许接收的帧的序号,称为接收窗口。发送窗口和接收窗口的序号的上下界不一定要一样,甚至大小也可以不同。不同的滑动窗口协议窗口大小一般不同。发送方窗口内的***代表了那些已经被发送,但是还没有被确认的帧,或者是那些可以被发送的帧。
滑动窗口
TCP的滑动窗口主要有两个作用,一是提供TCP的可靠性,二是提供TCP的流控特性。同时滑动窗口机制还体现了TCP面向字节流的设计思路。
发送窗口和接收窗口:
TCP是全双工的协议,会话的双方都可以同时接收、发送数据。TCP会话的双方都各自维护一个“发送窗口”和一个“接收窗口”。其中各自的“接收窗口”大小取决于应用、系统、硬件的限制,但是tcp的传输速率不能大于应用的数据处理能力,否则就会缓冲区淹没。各自的“发送窗口”则取决于对端通告的“接收窗口”,也就是取决于接收的缓冲区的大小。
发送窗口只有在收到对端对于本段发送窗口内字节的ACK确认,才会移动发送窗口的左边界。
接收窗口只有在前面的所有数据确认收到的情况下,才会移动左边的窗口。当在前面还有未接受的字节,而后面的字节已接收的情况下,窗口也不会移动,并不会对后续的字节进行确认。一次确保对端会对这些未收到的数据进行重传。主要涉及到接收端的累积确认接收机制。
最基本的传输可靠性来源于“确认重传”机制。
TCP的滑动窗口的可靠性也是建立在“确认重传”基础上的。
发送窗口只有收到对端对于本段发送窗口内字节的ACK确认,才会移动发送窗口的左边界。
接收窗口只有在前面所有的段都确认的情况下才会移动左边界。 当在前面还有字节未接收但收到后面字节的情况下,窗口不会移动,并不对后续字节确认。以此确保对端会对这些数据重传。
滑动窗口协议
- 停等协议(stop-and-wait):这时接受方的窗口和发送方的窗口大小都是1,1个比特就够表示了,所以也叫1比特滑动窗口协议。发送方这时自然发送每次只能发送一个,并且必须等待这个数据包的ACK,才能发送下一个。虽然在效率上比较低,带宽利用率明显较低。
- 后退n帧协议:这也是滑动窗口协议真正的用处,这里发送的窗口大小为n,接受方的窗口仍然为1。具体看下面的图,这里假设n=9:
首先发送方一口气发送10个数据帧,前面两个帧正确返回了,数据帧2出现了错误,这时发送方*重新发送2-8这7个帧,接受方也必须丢弃之前接受的3-8这几个帧。
后退n协议的好处无疑是提高了效率,但是一旦网络情况糟糕,则会导致大量数据重发,反而不如上面的停等协议,实际上这是很常见的,具体可以参考TCP拥塞控制。 - 选择重传:后退n协议的另外一个问题是,当有错误帧出现后,总是要重发该帧之后的所有帧,毫无疑问在网络不是很好的情况下会进一步恶化网络状况,重传协议便是用来解决这个问题。原理也很简单,接收端总会缓存所有收到的帧,当某个帧出现错误时,只会要求重传这一个帧,只有当某个序号后的所有帧都正确收到后,才会一起提交给高层应用。重传协议的缺点在于接受端需要更多的缓存。
拥塞控制
拥塞控制是一种分布式的用于实现多个竞争数据流共享网络资源的算法。其中拥塞则被定义为由于网络资源过载,从而导致网络用户侧观测到的概率性丢包以及时延的状态,而网络资源过载导致了网络的空间以及时间复用的效用降低。
TCP的拥塞控制由4个核心的算法组成:慢启动(slow start)、拥塞避免(Congestion voidance)、快速重传(Fast Retransmit)和快速恢复(Fast Recovery)。
慢启动
该算法的思想主要是一种探测一下网路的拥塞程度,就是不要一开始就发送大量的数据,也就是说有小到大逐渐增加(指数)拥塞窗口的大小。
拥塞避免
如果按上述的慢启动的思想如果不加以控制的话,毫无疑问的发生网络拥塞,当cwnd很快增长上来的时候,也很快利用了网络的资源,但是cwnd不能一直这样增长,一定需要某个限制。TCP使用了一个慢启动门限(ssthresh)的变量,当cwnd超过该值后,慢启动结束,进入拥塞避免阶段。对于大多数的TCP是吸纳来说,ssthresh的值是65535(同样以16bit来计算)。 拥塞避免的思想就是转指数增大变为加法线性增大。这样就可以避免增长过快导致网路拥塞,慢慢的增加调整到网络的最佳值。
快速重传
RTO超时重传会导致TCP传输效率较低。目前Linux TCP实现是采用ACK或者SACK的机制来实现对数据包进行累积确认,预测数据包丢失,实现快速重传。快速重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置重传计时器时间到期。实际上,目前Linux的TCP快速重传算法,除了经典的三次ACK,还包括ER、FACK,以及最新的基于时间序的RACK的包丢失快速重传算法,做出了很多改良。
快速恢复
其实快速恢复并不是单独存在的,它是快速重传的后续处理。通常认为客户端接收到3个ACK后,就会开始快速重传,但是如果还有更多的重复ACK呢,这个时候就是快速恢复要做的。
一些问题
- Q1 为什么在TCP协议里,建立连接是三次握手,而关闭连接却是四次握手呢?
因为当处于LISTEN 状态的服务器端SOCKET当收到SYN报文(客户端希望新建一个TCP连接)后,它可以把ACK(应答作用)和SYN(同步作用)放在同一个报文里来发送给客户端。但在关闭TCP连接时,当收到对方的FIN报文时,对方仅仅表示对方没有数据发送给你了,但未必你的所有数据都已经全部发送给了对方,所以你大可不必马上关闭SOCKET(发送一个FIN报文),等你发送完剩余的数据给对方之后,再发送FIN报文给对方来表示你同意现在关闭连接了,所以通常情况下,这里的ACK报文和FIN报文都是分开发送的。
- Q2 为什么TIME_WAIT 状态还需要等2*MSL秒之后才能返回到CLOSED 状态呢?
因为虽然双方都同意关闭连接了,而且握手的4个报文也都发送完毕,按理可以直接回到CLOSED 状态(就好比从SYN_SENT 状态到ESTABLISH 状态那样),但是我们必须假想网络是不可靠的,你无法保证你(客户端)最后发送的ACK报文一定会被对方收到,就是说对方处于LAST_ACK 状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT 状态的作用就是用来重发可能丢失的ACK报文。
- Q3 关闭TCP连接一定需要4次挥手吗?
不一定,4次挥手关闭TCP连接是最安全的做法。但在有些时候,我们不喜欢TIME_WAIT 状态(如当MSL数值设置过大导致服务器端有太多TIME_WAIT状态的TCP连接,减少这些条目数可以更快地关闭连接,为新连接释放更多资源),这时我们可以通过设置SOCKET变量的SO_LINGER标志来避免SOCKET在close()之后进入TIME_WAIT状态,这时将通过发送RST强制终止TCP连接(取代正常的TCP四次握手的终止方式)。但这并不是一个很好的主意,TIME_WAIT 对于我们来说往往是有利的。
分析网络情况
常用监控指标
- 网络吞吐 一秒钟发送接收多少字节
通常观测网络的出流量、入流量、流量峰值等网络发包 一秒钟发送接收多少包数 TCP连接数 单位时间内的丢包数/请求成功率
使用工具 iftop 查看
* 几个常用的:TX,发送流量;RX,接收流量;TOTAL,总流量;Cumm,运行iftop期间流量;peak,流量峰值;rates,分别代表2秒、10秒、40秒的平均流量。
iftop 功能全面
* -i 设定监测的网卡,如:# iftop -i eth1
* -B 以bytes为单位显示流量(默认是bits),如:# iftop -B
* -n 使host信息默认直接都显示IP,如:# iftop -n
* -N 使端口信息默认直接都显示端口号,如: # iftop -N
* -F 显示特定网段的进出流量,如# iftop -F 10.10.1.0/24或# iftop -F 10.10.1.0/255.255.255.0
* -h 帮助,显示参数信息
* -p 使用这个参数后,中间的列表显示的本地主机信息,出现了本机以外的IP信息;
* -b 使流量图形条默认就显示;
* -f 过滤计算包用的;
* -P 使host信息及端口信息默认就都显示;
* -m 设置界面最上边的刻度的最大值,刻度分五个大段显示,例:# iftop -m 100Miftop 操作
* 按 h 切换是否显示帮助;
* 按 n 切换显示本机的IP或主机名;
* 按 s 切换是否显示本机的host信息;
* 按 d 切换是否显示远端目标主机的host信息;
* 按 t 切换显示格式为2行/1行/只显示发送流量/只显示接收流量;
* 按 N 切换显示端口号或端口服务名称;
* 按 S 切换是否显示本机的端口信息;
* 按 D 切换是否显示远端目标主机的端口信息;
* 按 p 切换是否显示端口信息;
* 按 P 切换暂停/继续显示;
* 按 b 切换是否显示平均流量图形条;
* 按 B 切换计算2秒或10秒或40秒内的平均流量;
* 按 T 切换是否显示每个连接的总流量;
* 按 l 打开屏幕过滤功能,输入要过滤的字符,比如ip,按回车后,屏幕就只显示这个IP相关的流量信息;
* 按 L 切换显示画面上边的刻度;刻度不同,流量图形条会有变化;
* 按 j 或按 k 可以向上或向下滚动屏幕显示的连接记录;
* 按 1 或 2 或 3 可以根据右侧显示的三列流量数据进行排序;
* 按 < 根据左边的本机名或IP排序; 按 > 根据远端目标主机的主机名或IP排序;
* 按 o 切换是否固定只显示当前的连接;
* 按 f 可以编辑过滤代码;
* 按 ! 可以使用shell命令;
* 按 q 退出监控。
指标计算
事实上Linux上的工具都是通过系统文件计算出各项指标,因此我们也可以直接使用这些文件进行计算,这样可以保留最原始的精度。
- 出入流量和收发包数
通过/proc/net/dev文件,可以计算出服务器的流量及包量。
> 跟记录CPU信息的/proc/stat文件类似,/proc/net/dev中的数值,也是从系统启动后一直累加的。在32位系统上,/proc/net/dev中的数值系统使用4个字节的无符号整型保存,当数值达到2^32-1,即4294967295之后,数值会溢出,计算流量包量时需要把这一点考虑进去。而64位系统中/proc/net/dev使用的是8个字节的无符号整型,因此就不需要注意溢出的问题。
- TCP连接数、UDB接收和发送数据报数量
/proc/net/snmp记录了一些TCP信息,其中的CurrEstab字段,即当前已建立的TCP连接数。
/proc/net/snmp还记录了一些UDP信息,其中InDatagrams及OutDatagrams字段,即接收和发送的数据报数量。