多台电脑利用交换机连接,然后通过路由器将多个交换机连接起来,最后这种互相有联系的网络就形成了互联网。
因特网:全球最大的互联网。
给某片区域分配一个网段,通过IP地址就可以判断出区域。
通过域名查看IP地址
nslookup www.baidu.com
协议分层:协议的封装。
OSI七层模型:各层功能划分的更明确,各司其职。
分层带来的好处:
1.提供更模块化的设计,灵活性强;
2.结构上可以分开;
3.方便实现和维护;
4.有利于标准化。
----------------------------------------------------------------------------------------
物理层:以"0"、"1"代表电压的高低,灯光的闪灭,界定连接器和网线的规格。
电气特性,规定了设备的规范(8根网线,RJ-45 水晶头)。
传输的数据是二进制的比特流
这一层的设备:网卡(NIC) 光纤 集线器 双绞线。 网线最多传100m
----------------------------------------------------------------------------------------
数据链路层:互联(相邻)设备之间传送和识别数据帧。 数据成帧(加上帧头帧尾以及校验位)(数据来源去向以及检测错误(CRC循环冗余校验码))
只负责同一网段的数据传输。
封装成帧,透明传输,差错检测。
ipconfig/all windows上查看MAC地址信息
MSS:最大报文段(不包含IP报头和TCP报头):通过协商得出(1500-20-20 = 1460)。
封装成帧
帧头和帧尾的作用就是进行帧定界(即就是确定帧的界限),为了提高帧的传输效率,应当使得帧的数据部分长度尽可能地大于首部和尾部的
长度。每一种链路层协议都规定了帧的数据部分的长度上限,那就是MTU(最大传送单元,以太网中的默认值为1500字节)。
ARP数据包不足46字节,要在后面补充0。
MTU表示数据链路层的数据帧能承载的数据长度的上限。
MTU对IP的影响
1.将较大的IP包分成多个小包,并且给每个小包打上标签;
2.每个小包IP协议头的16位标识都是相同的;
3.每个小包的IP协议头的3位标志字段中,第二位为0,表示允许分片,第3位来表示结束标记(当前是否是最后一个小包,
是的话置为1,不是置为0);
4.到达对端时,再将这些小包按顺序重组,拼装到一起返回给传输层;
5.一旦这些小包中任意一个小包丢失,接收端的重组就会失败,但是IP层不会负责重新传输数据。
MTU对UDP的影响
1.一旦UDP携带的数据超过1472(1500-20-8),那么就会在IP层分成多个IP数据报
2.这多个IP数据报有任意一个丢失,都会引起接收端IP层重组失败,那么意味着如果UDP数据报在网络层分片,
整个数据被丢失的概率大大增加了。
MTU对TCP的影响
1.TCP的一个数据报也不能无限大,还是受制于MTU。TCP的单个数据报的最大消息长度,称为MSS(Max Segment Size);
2.TCP在建立连接的时候,通信双方会进行MSS协商;
3.双方在发送SYN的时候会在TCP头部写入自己能支持的MSS值;
4.然后双方得知对方的MSS值之后,选择较小的作为自己的MSS值。
假如发送端在尚未发送完一个帧时突然出现故障,中断了发送,但随后又很快恢复正常,于是重新从头开始发送未发完的帧,由于使用了
帧定界符,接收端就知道前面收到的数据是个不完整的帧(只有SOH的帧头,没有EOT帧尾),必须丢弃,如果有明确的帧定界,应当收下。
透明传输
字节填充法:在数据中出现的字符"EOT"实际上是个二进制数据00000100,因此在接收数据链路层的数据时,给控制字符前面加上转义字符
"ESC",那么当接收端收到连续的两个转义字符时,就删除其中一个。
差错检测
比特差错:比特流在传输过程中可能会出现0变成1,1变成0的情况。
使用CRC校验,能够实现无比特差错的传输,但是这并不是可靠传输。(帧丢失、帧重复、帧失序)
因此在CRC检错的基础上,增加了帧编号、确认和重传机制。
改正差错的任务交给TCP协议来完成。
PPP协议
链路:没有其他设备的一段线路。 自动匹配带宽
在最底层,网络可以由两台或者更多台计算机通过某种物理介质直接相连。
能收到哪些数据?
发给自己的,广播数据(广而告之),组播数据(类似于群广播)。
首先发送ARP广播,询问某个ip地址(ip地址映射一个MAC地址)是谁的?其次如果有人响应,那么就找到了,如果一直没人响应,
就丢弃该数据帧。广播发送ARP请求,单播发送ARP应答。(注意:ARP广播请求不能跨越路由器)
ARP高效运行的关键在于每一个主机或者路由器上都有一个ARP高速缓存,这个高速缓存中存放了"IP地址-MAC地址"的绑定。
每个ARP请求中都包含发送站的绑定信息,接收站在处理ARP请求时,会更新高速缓存中发送站的地址绑定信息。假如A中保存了B
的绑定信息,B突然发生故障,那么A将继续把IP分组发送给B。也就是说,A无法知道自己的ARP高速缓存中的信息什么时候失效。
在ARP高速缓存的管理中,使用了超时计时器,每一个地址绑定对应的一个计时器。当计时器超时后,就会删除该地址绑定信息,
典型的超时时间是20min。如果A发送了ARP请求给B,但是B没有响应,那么A就认为B已经下线了。
硬表比哈希表查找更快。
ARP分组格式
1.硬件类型:16bit字段,定义运行ARP的物理网络的类型,比如以太网的类型值是1。
2.协议类型:16bit字段,定义发送方提供的高层协议类型,比如IPv4,该字段值为(0800)
3.硬件长度:8bit字段,定义以字节为单位的MAC地址长度,比如以太网的MAC地址长度为6。
4.协议字段:8bit字段,定义以字节为单位的逻辑地址长度,比如IPv4的长度为4。
5.操作:16bit字段,定义分组的类型,对于ARP分组,1表示请求分组,2表示应答分组。
6.发送站硬件地址、发送站协议地址、目的站硬件地址、目的站协议地址。
ARP分组是直接封装在数据链路层的帧中进行传输的。
传输的数据:以太网帧(给物理层的二进制数据添头加尾) 源机器的MAC地址和目标机器的MAC地址
这一层的设备:早期的交换机 网桥 网卡驱动 蓝牙 MAC地址(6字节48位) PPP协议
以太网的MAC帧
目的MAC地址(6字节),源MAC地址(6字节),类型字段(2字节,标志上一层使用的是什么协议,0800表示IP协议,0806表示ARP协议,
8035表示RARP协议),数据(46-1500),帧检测序列FCS(4字节)。
MAC地址:16进制数字加上冒号的形式来表达。
网桥依靠转发表来转发帧。处于相同网段的接口不需要借助于网桥的转发。
以太网不是一种具体的网络,而是一种技术标准。
MAC地址通常是唯一的,虚拟机中的MAC地址不是真实的MAC地址,可能会冲突。有些网卡支持用户修改MAC地址。
arp -a 查看ip地址对应的MAC地址(显示当前的ARP地址表)
arp -s ip MAC 手动修改MAC地址(在ARP地址表中增加主机的"IP-MAC"绑定)
arp -d ip MAC 删除ARP表中绑定信息
-----------------------------------------------------------------------------------------
网络层:地址管理(IP划分)和路由选择。
路由:在网上找一个最优路径,把数据从源地址送到目标地址。 数据的转发
只能传输到某个机器(尽最大可能去传输,但是有可能失败),具体传输到什么上是在传输层。
负责将数据尽可能地送到目的地,但是不保证一定能够送得到。
主机:配有IP地址,但是不进行路由控制的设备;
路由器:配有IP地址,又能进行路由控制;
节点:主机和路由器的统称。
路由选择
直接交付
分组的最终目的站与交付者(路由器)在同一个网络时实现的交付方式。
间接交付
发送站使用IP分组的目的IP地址和路由表来找到下一个路由器的IP地址,分组必须要交付到这个路由器。
查看windows中的路由表
route print
网络目的地址
列出了路由器连接的所有网段
网络掩码
列出了对应目的网络地址的子网掩码,需要注意,这里的网络掩码不是本主机中设置的子网掩码值。
网关
列出了要到达目的网络需要把分组转发的下一跳地址
接口
列出了哪一个网卡连接到了合适的目的网络
度量
若有多条路径发送一个分组,则可以根据度量值选择一条最佳路径。 指定路由跳数。
route -p
使得指定的路由保持不变,一般情况下,重启的时候任何路由信息都会被删除,-p告诉系统一直保留该路由信息。
route -f
清除路由表中所有的网关输入记录。
show ipaddress route
查看路由表
查看linux中的路由表
route
路由表中的关键信息 目的IP 子网掩码 接口(LAN口还是WAN口)
default是全为0的IP,此时如果没有找到匹配的IP,往往就会找路由器的WAN口(从eth0口转发出去),
然后再去找上级路由器的LAN口。
路由器转发IP分组的时候,从某一条路由表中得到下一跳地址后,并不是将下一跳地址填入到该IP分组首部,而是把它送交给
下层的网络接口软件。网络接口软件负责将下一跳地址映射到MAC地址(ARP协议),通过数据链路层的以太网帧将该IP分组发送到
下一跳路由器上。
协议头格式
4位版本 4位首部长度(选项可用40个字节) 8位服务类型(TOS) (4种状态转换,并且是互斥的) 16位总长度(IP数据报长度:字节数)
16位标识(标识发送的报文) 3位标志 13位片偏移(方便排序)
8位生存时间(TTL) 8位协议(交给哪个传输层协议) 16位首部校验和 32位源IP地址 32位目的IP地址 选项(如果有) 数据
报头20个字节
IP划分:
一个IP数据报由首部和数据两部分组成,共32位。
IP协议版本占4位,分IPv4和IPv6。
注意:传送的数据报长度如果超过数据链路层的MTU,就必须把过长的数据报进行分片处理。
每一个IP数据报越短,路由器转发的速度就越快。
标志,占3位,标志字段的最低位记为MF(MF=1表示还有分片,MF=0表示这已经是最后一个分片)
数据报首部的第一个4bit是版本号,第2个4bit是首部长度。
DF(意思是"不能分片",DF=0时才允许分片)
片偏移以8个字节为偏移单位 一开始分包是IP头,TCP头,数据,接下来是IP头,数据等等。
TTL:生存时间,表示数据报在网络中的寿命,当TTL减为0时,丢弃这个数据报。现在TTL的单位不再是秒,而是跳数。
数据报能在因特网中经过的最大路由器的最大数值是255。
这一层的设备:路由器
网络地址中最后一个为1的一般表示路由器。
ip地址网段划分
5类IP划分由于对IP地址大量浪费,因此没被推广起来。引入CIDR划分方案,子网掩码。
网络地址 = IP地址 & 子网掩码
网络号:相邻的两个网络不能有相同的网络号
主机号:同一个局域网中,主机之间具有相同的网络号,不能有相同的主机号(ip冲突)
特殊的IP地址
主机号全为1表示广播地址
主机号全为0表示局域网地址
127.0.0.1本地环回地址(虚拟网卡地址) 自己发自己答
私有IP地址和公有IP地址
10.*,前8位是网络号,共16,777,216个地址
172.16.到172.31.,前12位是网络号,共1,048,576个地址
192.168.*,前16位是网络号,共65,536个地址 包含在这个范围中的, 都成为私有IP, 其余的则称为全局IP(或公网IP)。
分片针对UDP
IP不够用
1.DHCP分配; (只给接入网络的设备分配IP地址,因此同一个MAC地址的设备,每次接入互联网中得到的IP地址不一定相同。)
2.NAT地址转换。(NAPT建立IP:PORT的映射) 用一个外网IP来代替一大堆的内网IP(相当于快递只精确到小区即可)
NAPT通过端口号来区分这个数据应该交给局域网中哪个设备
3.IPv6(v4 和 v6不兼容,推广不起来)
4.网段划分
经典划分方式ABCDE五类(IP地址浪费太严重)
CIDR(引入子网掩码)
为什么要有网络号和主机号?
为了缩小查找网段的范围,这样查找起来高效。 (eg:捡到书根据学号判断院系的过程)
不同的子网其实就是把网络号相同的主机放到一起。
如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号必须不能和子网中的其他主机重复。
有一种技术叫做DHCP, 能够自动的给子网内新增主机节点分配IP地址, 避免了手动管理IP的不便.
一般的路由器都带有DHCP功能. 因此路由器也可以看做一个DHCP服务器。
路由选择
网关地址:路由器的内网
WAN口:外网的网口(wan ip)
LAN口:内网的网口(lan ip) 局域网
并且这两个IP处于不同的网段。
改善家里一个路由器因为承重墙导致信号不好
桥接一个路由器(插入WAN口推荐,实际上插入LAN口(LAN口IP变成192.168.0.1)也可以) 备份路由器
拓扑
线段之间的距离不代表真实长度。
路由器转发
源IP会被替换成WAN网IP
路由(唐僧问路例子)
一跳一跳问路的过程,所谓"一跳"就是数据链路层中的一个区间,具体是在以太网中从源MAC地址到目的MAC地址之间的帧传输区间。
在路由表中,对每一条路由最主要的是以下两个信息:(目的网络地址,下一跳地址)
route命令查看路由表(linux) 目的IP 子网掩码 网络接口 下一跳表项
路由选择过程
待转发的IP数据报,取出其中的目的IP和子网掩码进行按位与操作,和路由表中的表项进行对比,如果匹配就从
对应的网络接口中进行转发,反之就走下一跳表项。
网络地址 = IP地址 & 子网掩码
使用子网划分后,路由表必须包含以下三项内容:目的网络地址、子网掩码和下一跳地址
tracert(windows) 跟踪一个分组从源点到终点的路径。
traceroute(linux) 让发送的UDP用户数据报故意使用一个非法的UDP端口,ICMP就返回"端口不可达"的差错报文。
RIP路由信息协议
VPN虚拟专用网(目的ip与源ip地址一样)
NAT网络地址转换:在NAT路由器上将本地地址转换为全球IP地址,才能与因特网连接。
RARP(逆地址解析协议): 将MAC地址映射为IP地址
传输的数据:数据报(IP数据报)
ICMP协议( 1 网际控制报文协议)用来报告出错信息(ping也用的这个协议icmp_seq) TTL(Time To Live,生存时间,占8位)
的值linux默认是64,每经过一个路由器就减去1。
目标不可达 3 ping命令没有端口号
IGMP协议( 2 网际组管理协议) 管理组播数据
|
v
IP协议(网际协议,32位。 类型字段,6表示TCP,17表示UDP)
|
v
ARP协议(地址解析协议):从网络层的IP地址解析出数据链路层使用的MAC地址
--------------------------------------------------------------------------------------
传输层:管理两个结点之间的数据传输,负责可靠传输(确保数据被可靠地传送到目标地址)。
可以理解为传输数据到哪个进程。负责将数据交给具体的进程。
通过端口识别数据传送到哪一个进程。保证数据的可靠送达。(每次发送完数据后会通知对方接收,对方响应后也会发送给发送方。)
流量控制:假如A的接收速度是10M/s,B的接收速度是30M/s,那么在收发数据的时候会做调整,A->B发送30M/s,B->A发送10M/s。
两个机器之间接收数据的能力
拥塞控制:发现网不好的时候,发数据就变的慢一点,网好了,再发数据快一点。
整个网络的拥堵程度
UDP(用户数据报协议):不需要保证可靠传输的协议,传送数据前不需要建立连接。 DNS使用的是UDP传输
需要注意的是,UDP没有流量控制和拥塞控制,并且如果传输的数据的大小超过了1500字节,直接丢弃该报文。
特征: 寄信例子 只管寄出去,不管收件人能否收到。
1.无连接的;(减少了开销和发送数据之间的时延) 知道了对端的IP和PORT就可以直接传输,不需要建立连接。
(按下发送就发出去了)
2.尽最大努力交付; (不保证可靠交付)
没有确认和重传机制,如果因为网络故障数据无法发送给对端,UDP协议也不会给应用层返回任何错误信息。
3.面向报文的; (面对应用层发过来的报文,既不合并也不拆分,而是保留这些报文的边界)
也就是说,UDP一次交付一个完整的报文。 收发数据不够灵活,但是可区分数据报是哪个(数据之间间隔很明显)。
不能够灵活地控制读写数据的次数和数量,也就是说,如果发送了10K数据,但是接收端取的时候只取了1K,那么9K将丢失。
假如发送100K数据,也不能分成10次发送。
4.没有拥塞控制和流量控制;
5.支持一对一、一对多、多对一和多对多的交互通信;
6.UDP的首部开销小。(UDP首部只有8个字节,TCP首部有限数据占20个字节)
7.全双工:通过一个UDP的socket既可以读,也可以写。
UDP的首部格式(每个字段的内容都是2个字节,头部一共8个字节)
16位源端口:不需要时可用全0
16位目的端口
16位UDP长度:UDP用户数据报(UDP头部+UDP数据)的长度,其最小值为8 最大长度是65535(包含UDP头部)
16位检验和:检验UDP用户数据报在传输中是否有错,若有错就丢弃。
包含数量 截取长的字符串,提取有效部分,最终生成一个校验码,发送端和接收端只需要比较校验码就可以了。
1.如何把10G文件传输到服务器2上?
网络传输
2.Linux中使用哪个指令?
scp远程拷贝指令
3.如何验证文件传输过程中是否出错?
比较文件内容(适用于小文件)
分别对两个文件计算校验和,最后比较校验和即可。
4.在linux中使用哪个指令来计算文件的校验和?
md5sum计算文件的md5值,比较md5值
UDP长度可以来区分UDP传输的数据,减去8个字节就是数据的长度。最大是64K(包含UDP首部)
UDP缓冲区
UDP没有真正意义上的发送缓冲区,调用sendto会直接交给内核,由内核将数据传给网络层协议进行后续的传输;
UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的UDP报文的顺序和发送UDP报文的顺序一致,如果UDP缓冲区满了,再次
到达的UDP数据就会被丢弃。
基于UDP的应用层协议
NFS: 网络文件系统
TFTP: 简单文件传输协议
DHCP: 动态主机配置协议
BOOTP: 启动协议(用于无盘设备启动)
DNS: 域名解析协议
如果我们需要传输的数据超过64K, 就需要在应用层手动的分包(分成多个UDP包), 多次发送, 并在接收端手动拼装。
UDP无法保证包序,需要在应用层进行编号。
UDP适用于
实时性 VoIp视频传输
交互性应用 QQ MSN
支持组播广播
保持开销小又可靠地传输:TFTP
TCP(传输控制协议) :需要保证可靠传输的协议, 面向连接的服务。
在传送数据前必须先建立连接,数据传送结束后要释放连接。TCP不提供广播或者多播服务,由于TCP要提供可靠的、面向连接的
运输服务,因此不可避免的增加了许多的开销,如确认请求、流量控制以及连接管理等等。
特征:
1.是面向连接的传输层协议。
应用程序在使用TCP协议前必须先建立TCP连接,在传输数据完毕后,必须释放已经建立的TCP连接。实际上,应用进程之间的
通信像是在"打电话",通过前要先拨号建立连接,通话结束后要挂机释放连接。
2.每一条TCP连接只能有两个端点(点对点)。
3.TCP提供可靠交付的服务。(无差错、不交付、不重复、并且按序到达)
4.TCP提供全双工通信。
5.面向字节流。(流入到进程或者从进程流出的字节序列)
协议段格式
16位源端口号 16位目的端口号 32位无符号的序号(类似于学号,标识作用) 32位确认序号
4位首部长度(4位可以表示0-15) 保留6位(URG ACK PSH RST SYN FIN) 16位窗口大小
URG: 紧急指针是否有效
ACK: 确认号是否有效
PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走
RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段(发现连接有问题)
浏览器显示连接已重置 TCP协议中的RST标志位重置
一方关闭,另一方还在发数据,就会触发RST标志位。 重新连接
SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段
FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段
16位校验和: 发送端填充, CRC校验. 接收端校验不通过, 则认为数据有问题. 此处的检验和不仅包含TCP首部, 也包含TCP数据部分.
16位紧急指针: 标识哪部分数据是紧急数据。
40字节头部选项
TCP首部最大60个字节(15*32/8=60)
三次握手重要状态
LISTEN 准备好了允许客户端建立连接
ESTABLISHED 连接建立完毕,可以交互数据了
四次挥手重要状态
CLOSE_WAIT 如果服务器上出现大量的这个状态,意味着文件描述符没有关闭(bug)
TIME_WAIT 进程退出,但是连接还不能退出,如果最后一个ACK丢包了,可以借助这个TIME_WAIT状态的连接进行ACK重传
谁主动断开连接,谁就进入TIME_WAIT状态。
持续时间:2MSL
如果服务器上出现大量的这个状态,此时服务器是主动断开连接的一方。可以使用SO_REUSEADDR选项重用端口号。
确认应答
TCP可靠传输的核心
可靠性的意思不是说发送的数据100%就能到达,而是说对端没收到数据,发送方能够感知到。
确认序号
ACK需要明确指出确认的是哪一条数据
确认序号表示该序号之前的所有数据都收到了
TCP三次握手中第三次连接失败,这时候会发送RST重置连接状态,就会断开连接,重新建立连接。
序列号不一定从0开始。若超过32位序列号,就会重新分配序列号。
并不知道数据多长,通过序列号排序。
如何保证TCP的可靠传输?
1.确认应答机制
每一个ACK都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据,下一次你从哪里开始发。
eg:讲笑话例子
TCP将每个字节的数据都进行了编号,即就是序列号。
序号是按照字节(字符数组)来发送的,确认应答中发送了下一次要发送的数据从哪里开始,并且有之前的数据已经收到了的含义。
2.超时重传机制
停止等待协议
每发送完一个分组就停止发送,等待对方的确认,在收到确认后再发送下一个分组。
超时重传(1.丢数据;2.丢ack)
A只要超过了一段时间仍然没有收到确认,就认为刚才发送的分组丢失了,因而会重传前面发送过的分组,这就叫做超时重传。
要实现超时重传,就要在每次发送完一个分组设置一个超时计时器,如果到定时时间之前收到了对方的确认,就撤销已经设置的计时器。
1.A在发送完一个分组后,必须暂时保存已经发送的分组的副本,只有在收到相应的确认后才会清除掉这个副本。
2.分组和确认分组必须进行编号,这样才能明确哪一个发送出去的分组收到了确认,而哪些分组没有收到确认。
超时时间的确定(动态计算超时时间)
随着网络的不同,这个时间的长短是有差异的,时间太长,会影响整体的重传效率,时间太短,会频繁发送重复的包。
超时重传时间以指数形式递增(N*500ms),累计到一定的重传次数,TCP认为对端主机出现异常,强制关闭连接。
3.序列号
ack丢失了,此时主机B收到很多重复数据,那么TCP协议需要识别出哪些是重复的包,并且把重复的丢弃掉,这时候利用序列号,
可以很好地达到去重的效果。
4.连接管理(面向连接)
在可靠传输的基础上,考虑如何提高传输效率。
提高TCP传输效率
滑动窗口
在不等待ACK到达的前提下,发送方批量发送的数据是多少
流量控制中的窗口
根据接收方缓冲区的剩余空间决定发送方的窗口大小
拥塞控制中的窗口 恋爱曲线图 (慢启动)
发送方按照一定的规则来试探网络的拥堵程度
1.滑动窗口机制;
对于每一个发送的数据段, 都要给一个ACK确认应答。收到ACK后再发送下一个数据段。这样做有一个比较大的缺点, 就是性能较差。
尤其是数据往返的时间较长的时候。既然这样一发一收的方式性能较低, 那么我们一次发送多条数据, 就可以大大的提高性能
(其实是将多个段的等待时间重叠在一起了)。
操作系统内核为了维护这个滑动窗口, 需要开辟发送缓冲区来记录当前还有哪些数据没有应答。只有确认应答过的数据,
才能从缓冲区删掉。窗口越大, 则网络的吞吐率就越高,传输效率越好。
一次性发送很多数据,然后在队列中等待。 由接收方调节,定义一个窗口大小。 批量发送,批量等待。
在不用等待ACK的情况下,最多可以发送的数据的多少。窗口大小指的是无需等待确认应答而可以继续发送数据的最大值。
等到第一段数据的ACK后,窗口向后滑动,继续发送数据。
快重传:也称作高速重发机制,实际上是接收缓冲区中已经存放了之前存放的数据。
如果出现了丢包,如何进行重传?
1.数据报已经抵达,ACK丢了。
这种情况下,部分ACK丢了并不要紧,因为可以通过后续的ACK进行确认。
2.数据包直接丢了
假如发送1001-2000丢包了,那么上一次应答中一直发送接收1001之后的数据,由于丢包了,那就一直发送确认应答,
直到收到多个确认应答时进行重发。确认号会在后续的ACK中补充。 不会进行冗余的传输。
2.流量控制 (水位例子)
通过调整窗口大小来控制流量。 丢包问题 控制传输数据的速度。
接收端处理数据的速度是有限的,如果发送端端发的太快, 导致接收端的缓冲区被填满, 这个时候如果发送端继
续发送, 就会造成丢包, 继而引起丢包重传等等一系列连锁反应。因此TCP支持根据接收端的处理能力, 来决定发送端的发送速度。
这个机制就叫做流量控制(Flow Control)。
根据接收方的接收能力,实时调整窗口的大小。
1.接收端将自己可以接收的缓冲区大小放入TCP头部中的"窗口大小"字段,通过ACK通知发送端;
2.窗口大小字段越大,说明网络的吞吐量越高;
3.接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端;
4.发送端接受到这个窗口之后, 就会减慢自己的发送速度;
5.如果接收端缓冲区满了, 就会将窗口置为0;
6.这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端。
16位数字最大表示为65535,那么TCP窗口的大小就是65535字节吗?
实际上,TCP首部40字节选项中还包含了一个窗口扩大因子M,实际窗口大小是窗口字段的值左移M位。
3.拥塞控制 丢包问题 (水位例子)
一开始约定窗口大小(阈值),然后根据网络状况改变窗口大小,
TCP引入慢启动机制,先发少量的数据,探路,摸清当前的网络拥堵状态, 再决定按照多大的速度传输数据。
拥塞窗口增长速度是指数级的,当超过某个阈值时,就按照线性方式增长。
当TCP开始启动的时候, 慢启动阈值等于窗口最大值。
在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回1。
4.延迟应答 (等一段时间,水位到一定高度时,再放水)
如果接受数据的主机立刻返回ACK应答,那么返回的窗口大小可能比较小。
不想改变窗口大小,根据流量控制调整窗口大小,延迟一段时间再回复可能窗口就会变大。
具体的数量和超时时间, 依操作系统不同也有差异,一般N取2,超时时间取200ms
留出时间来处理缓冲区中的数据。
所有的包都可以延迟应答吗?
1.数量限制:每隔N个包就应答一次;
2.时间限制:超过最大延迟时间就应答一次。
5.捎带应答(延迟应答基础上)
确认应答中包含数据和确认,可以减少流量。
四次挥手就有可能变成三次挥手。
发送缓冲区为了超时重传数据,接收缓冲区为了数据去重。
粘包
粘包问题中的 "包" , 是指的应用层的数据包.(面向字节流相关) 数据报没有读取完全。
在TCP的协议头中, 没有如同UDP一样的 "报文长度" 这样的字段, 但是有一个序号这样的字段.
站在传输层的角度, TCP是一个一个报文过来的. 按照序号排好序放在缓冲区中.
站在应用层的角度, 看到的只是一串连续的字节数据.
那么应用程序看到了这么一连串的字节数据, 就不知道从哪个部分开始到哪个部分, 是一个完整的应用层数据包.
解决粘包(TCP传输的数据没有明显边界)
在应用层对传输过来的数据限制边界
1.指定数据报长度;
2.使用分隔符;(有了明显的边界)
3.TLV类型,把数据长度带回去
struct
{
uchar type;
uint64_t len;
uchar buf[0];
};
对于UDP协议来说,不存在粘包问题。
UDP头部有明确的报文长度(边界)。要么收到完整的UDP报文,要么收不到。
TCP异常
进程终止: 进程终止会释放文件描述符, 仍然可以发送FIN. 和正常关闭没有什么区别.
机器重启: 和进程终止的情况相同.
机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已经不在了, 就会进行reset。
即使没有写入操作, TCP自己也内置了一个保活定时器, 会定期询问对方是否还在. 如果对方不在, 也会把连接释放。
另外,应用层的某些协议,也有一些这样的检测机制。
例如HTTP长链接中,也会定期检测对方的状态,在QQ断线后,也会定期尝试建立连接。
接收方关闭socket,此时如果发送方没有close的话,发送方处于CLOSE_WAIT状态,
那么发送方想要写数据的时候,就会触发SIGPIPE信号。
保活定时器
如果一定时间内没有收到任何发送方发送的数据,此时就发一个心跳包。
客户主动与服务器建立连接后,后来客户端的主机突然出故障,显然服务器就不能接收到客户发来的数据。因此不能让服务器白白等下去,
使用保活计时器,当服务器每收到一次客户的数据,就重新设置保活计时器。通常设为两小时,如果两小时没有收到客户的数据,服务器就
发送一个探测报文段,每隔75分钟发送一次,若一连发送10个探测报文段仍无客户响应,服务器就认为客户端出故障了,接着关闭连接。
使用setsockopt()设置socket描述符的选项SO_REUSEADDR为1, 表示允许创建端口号相同但IP地址不同的
多个socket描述符。 不能因为timewait状态导致服务器不能立即重启。
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
TCP连接的端点叫做套接字或插口,IP地址:端口号 例如 192.3.4.5:80 端口号是一个2字节16位的整数。(0~65535)
注意:同一个IP地址可以有多个不同的TCP连接,而同一个端口号也可以出现在多个不同的TCP连接中。
一个端口只能被一个进程使用,但是一个进程可以使用多个端口。
一个进程可以绑定多个端口号
eg:一个进程可以创建多个socket,然后绑定多个端口号,每个端口号去执行不同的业务,例如qq文件传输,还有语音视频等。
通常一个端口号不能被多个进程绑定,特殊情况可以。(先绑定成功一个进程,然后fork出子进程,复制父进程的信息。)
协议端口号port 是个地址(由于每次创建进程,pid都会改变,因此用port来标识pid)
使用一个16位的端口号来标志一个端口,但是,端口号只具有本地意义,在因特网的不同计算机中,相同的端口号是没有关联的。
服务端使用的端口号0~1023 知名端口号
常见的端口号
FTP:21 SSH:22 TELNET:23 SMTP:25 DNS:53 HTTP:80 Mysql:3306 HTTPS:443
cat /etc/services 查看知名端口号
需要注意的是,80端口一定是Web服务,但是Web服务可以不用80端口。
传输的数据:数据段(TCP段)
基于TCP的应用层协议
HTTP HTTPS SSH Telnet FTP SMTP
TCP的运输连接管理
建立连接时可靠传输的一个前提。
共三个阶段,即就是连接建立,数据传送和连接释放。
TCP的连接建立
假设A运行的是TCP客户程序,而B运行TCP服务程序,最初两端的TCP进程都处于CLOSED状态,注意A主动打开连接,B被动打开连接。
B的TCP服务器进程先创建传输控制块TCB(存储了每一个连接中的一些重要信息,比如TCP连接表,到发送和接收缓存的指针,到重传队列的指针),
准备接受客户进程的连接请求,然后服务器进程就处于LISTEN状态,等待客户的连接请求。
A的TCP客户进程也是首先创建TCB,然后向B发送连接请求报文段,这时首部中的同步位SYN置为1,同时选择一个初始序号seq=x,TCP规定,
SYN报文段不能携带数据,但是要消耗一个序号,这时,TCP客户进程进入SYN-SENT(同步已发送)状态。
B收到连接请求报文段后,如果同意连接,则向A发送确认,在确认报文段中应把SYN和ACK置为1,确认号是ack=x+1,同时为自己选择一个
初始序号seq=y,注意这个报文段也不能携带数据,但是要消耗掉一个序号,这时TCP服务器进程进入SYN-RCVD(同步收到)状态。
TCP客户进程收到B的确认后,还要向B给出确认。确认报文段的ACK置1,确认号是ack=y+1,而自己的序号seq=x+1。TCP的标准规定,
ACK的报文段可以携带数据,但是如果不携带数据可以不消耗序号,在这种情况下,下一个数据报文段的序号仍是seq=x+1,这时,
TCP连接已经建立,A进入ESTABLISHED(已建立连接)状态。
当B收到A的确认后,也进入ESTABLISHED状态。
为什么A还要发送一次确认呢?
这主要是为了防止已经失效的连接请求报文段突然又传到了B,因而产生错误。
所谓"已失效的连接请求报文段"是这样产生的,A发出连接请求,但因连接请求报文丢失而未得到确认,于是A重传一次连接请求,后来收到
了确认,建立了连接,数据传输完毕后,就释放了连接。这种没有"已失效的连接请求报文段"
考虑一种异常情况,A发出第一个连接请求报文段并没有丢失,而是在某个网络节点长时间滞留了,以至于延误到连接释放以后的某个时间
才到达B。本来这是一个早已失效的报文段,但是B收到此失效的连接请求报文段后,就误以为A发出一次新的连接请求,于是向A发出确认报文段。
同意建立连接,假如不是三次握手,那么只要B发出确认,新的连接就建立了。
由于现在A并没有发出建立连接的请求,因此不会理睬B的确认,也不会向B发送数据,但是B却以为新的传输连接已经建立了,并且会
一直等待A发过来数据,那么B的许多资源就会被浪费掉。
采用三次握手的方法可以防止上述现象的产生,例如在刚才的情况下,A不会像B的确认给出确认,B由于接收不到确认,就知道
A并没有要求建立连接。
TCP的连接释放
数据传输结束后,通信的双方都可以释放连接。现在A和B都处于ESTABLISHED状态,A的应用进程先向其TCP发出连接释放的报文段,
并停止发送数据,主动关闭TCP连接,A把连接释放报文段首部的终止控制位FIN置为1,其序号为seq=u,它等于前面已经传送过数据的最后
一个字节加1,这时A进入FIN-WAIT1(终止等待1)状态,等待B的确认,注意,FIN报文段即使不携带数据,也会消耗掉一个序号。
B收到连接释放报文段后即发出确认,确认号是ack=u+1,而这个报文段自己的序号是v,等于B前面已经传送过的数据的最后一个字节的序号
加1,然后B进入CLOSE-WAIT(关闭等待)状态,TCP服务器进程这时候通知高层的应用进程,因而从A到B的连接就释放了。这时的TCP连接就处于
半关闭状态,即就是A没有数据要发送了,但是B若发送数据,A仍要接收,也就是说,从B到A这个方向的连接还没有关闭,这个状态可能会持续
一段时间。
A收到B的确认后,就进入FIN-WAIT2(终止等待2)状态,等待B发出的连接释放报文段。
若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接,这时B发出的连接释放报文段必须使得FIN=1。现在假定B的序号为w
(在半关闭状态下B可能又发送了一些数据),B还必须重复上次已经发送过的确认号ack=u+l。这时候B进入LAST-ACK(最后确认)状态,等待A确认。
A在收到B的连接释放报文段后,必须对此发出确认,在确认报文段中将ACK置为1,确认号ack=w+1,而自己的序号seq=u+1,然后进入到
TIME-WAIT(时间等待)状态,注意,此时TCP连接还没有释放掉,必须经过时间等待计时器设置的时间2MSL(也就是2min)后,A才进入CLOSED状态。
时间MSL叫做最长报文段寿命(Maximum Segment Lifetime),因此,从A进入TIME-WAIT状态后,要经过4分钟才能进入到CLOSED状态,才能开始
建立下一个新的连接。当A撤销相应的传输控制块TCB后,就结束了本次TCP连接。
为什么A在TIME-WAIT状态必须等待2MSL的时间呢?
1.为了保证A发送的最后一个ACK报文段能够到达B。这个ACK报文段可能丢失,因而处于LAST-ACK状态的B收不到对已发送FIN+ACK报文段
的确认。B会超时重传这个报文段,而A就能在2MSL时间内收到这个重传的FIN+ACK报文段。接着A重传一次确认,重新启动2MSL计时器,最后A
和B都正常进入到CLOSED状态。如果A在TIME-WAIT状态不等待一段时间,而是在发送完ACK报文段后立即释放连接,那么就无法收到B重传的
FIN+ACK报文段,因而也就不会再发送一次确认报文段,这样B就无法按照正常步骤进入CLOSED状态。
2.防止"已失效的连接请求报文段"出现在本连接中,A在发送完最后一个ACK后,再经过2MSL,就可以使得本连接持续的时间内所产生的
所有报文段都从网络中消失,这样就可以使得下一个新的连接中不会出现这种旧的连接请求报文段。
B只要收到A的确认后,就进入CLOSED状态,注意,B结束TCP连接的时间要比A早一些。
保证所有的数据消失。
TCP/UDP对比
TCP适用于可靠传输的情况,比如文件传输,重要状态更新等;
UDP适用于对高速传输和实时性要求较高的通信领域,比如早期的QQ视频传输,另外在传输层上UDP还可以用于广播。
1.UDP用于广播,TCP不能;
2.TCP内存开销大于UDP;(TCP有各种缓冲区,而且还有连接管理机制)
3.UDP传输效率高于TCP;
4.TCP对应用层数据报大小没有限制,但是UDP有64K的限制。
用UDP来实现可靠传输
1.引入序列号,保证数据顺序;
2.引入确认应答,确保对端收到了数据;
3.引入超时重传,如果隔一段时间没有应答,就重发数据。
-------------------------------------------------------------------------------------
最上面的三层是程序员工作的三层。
会话层:通信管理,负责建立和断开通信连接(数据流动的逻辑通路),管理传输层以下的分层。
它不参与传输,只是对数据传输过程进行管理。
建立连接,过程管理,断开连接。
netstat -an 查看所有的会话信息(windows)
netstat -nb 查看会话对应的进程信息 -n以数字形式显示地址和端口号
# netstat -a # 列出所有端口
# netstat -at # 列出所有TCP端口
# netstat -au # 列出所有UDP端口
# netstat -l # 只显示监听端口
# netstat -lt # 显示监听TCP端口
# netstat -s # 显示所有端口的统计信息
# netstat -p # 显示PID和进程名称
# netstat -r # 显示核心路由信息
LISTENING:正在监听,只有tcp端口才可以这样(如果是udp的话,那么肯定是木马)
ESTABLISHED:正在共享,表示两者连接着(如果135端口这样的话,注意杀毒)
CLOSE_WAIT:有过连接,现在已经结束了
表示层:设备固有数据格式和网络标准数据格式的转换。
加密数据,压缩文件或者数据,改变网络字节序
应用层:针对特定应用的协议。
凡是能够产生网络流量的进程都是应用层做的。 (应用层也会加个Appl的首部)
-------------------------------------------------------------------------------------
物数网传会表应
如何排除网络故障?
原则:从底层向上层排除。
1.检查网线是否插好,然后查看灯是否亮着,(这是从物理层去检查);
2.ipconfig查看MAC地址,然后查看ip地址对应的MAC地址是否一致;
3.ping -i 1 www.baidu.com // ping一个路由器,
如果请求超时,说明该服务器不允许ping 直到报错就可以知道哪个路由器出了故障;
pathping www.baidu.com 从0开始逐个排查路由哪个不通
4.DNS解析
上网的方式
B/S (Browser/Server) 通过浏览器来上网
C/S (Client/Server) 客户端得自己写
P2P (point 2 point) 下载速度快,因为获取下载的渠道多
TCP/IP
-----------------------------------------
数据链路层 驱动及硬件设备
以太网
-----------------------------------------
网络层 OS内核
传输层
TCP UDP IP ICMP IGMP ARP(将IP地址转换为MAC地址)
-----------------------------------------
应用层 用户写的应用程序
HTTP FTP SMTP(发邮件) POP3(收邮件) DNS
-----------------------------------------
网络协议栈:形象的反映了一个网络中文件传输的过程。 封装->分用(解包)
每一层看到的只有处于本层的协议。(对等通信)
不跨路由器(通过交换机连接,直通):局域网
跨路由器(多个路由器):广域网
一种比较好的IP地址使用方案
内部的互联网不管是否与因特网相连接,最好使用私有地址。若要与因特网相连接,只需要在网络的出口处作网络地址转换(NAT),
转换为分配到的合法的IP地址,这样一方面可以解决IP地址紧缺的问题,另一方面有利于提高网络的安全性。
子网划分的原因
解决IP地址被浪费的问题,从而提高IP地址的使用效率。
子网掩码除了点分十进制表示之外,有时也使用一种"斜杠"的格式,斜杠后面的数字表示子网掩码中1的个数。
eg: 172.69.11.20/24表示IP地址172.69.11.20的网络部分和子网部分共占24bit,另外的8bit是主机部分,对应的子网掩码就是255.255.255.0。