计算机网络基础
网络协议
协议:协议就是一种约定,就好比网友见面,彼此协商胸口插枝玫瑰花见面,这就是一种提前的约定,也可以称之为协议。
举例:
计算机生产商有很多,操作系统也有很多,计算机网络硬件设备也有很多,那么如何让不同厂商生产的计算机之间能够相互顺畅通信呢?就需要一个标准去约定,这个标准就是网络协议
。
1.OSI七层模型
- OSI(Open System Interconnection,开放系统互连)七层网络模型称为开放式系统互联参考模型,是一个逻辑上的定义和规范。
2.TCP/IP四层模型
TCP/IP通讯协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。四层分别是:
应用层
:负责应用程序之间的沟通,如简单电子邮件传输SMTP、文件传输协议FTP、网络远程访问协议Telnet等,网络编程指的就是针对应用层的编程。传输层
:负责两台主机的数据传输,如传输控制协议TCP,能够保证数据可靠地从源主机发送到目标主机。网络层
:负责地址管理和路由选择,例如在IP协议中,通过IP地址标识一台主机,并通过路由表地方式规划出两台主机之间的数据传输的线路(路由),能够确保数据可靠的从源主机发送到目标主机。数据链路层
:负责设备之间的数据帧的传送和识别,例如网卡设备的驱动、帧同步(就是说从网线上检测到什么信号算作新帧的开始)、冲突检测(如果检测到冲突就自动重发)、数据差错校验等工作;有以太网、令牌环网,无线LAN标准,路由器工作在网络层。
3.传输层
端口号
端口号:找到应用程序,比如一台主机QQ给另外一台QQ发消息,因为端口号标识一个应用程度,所以利用端口号标识目的主机QQ才收到了消息。
端口号范围:0-65535
端口号分类:
1.知名端口号:0-1023,比如FTP(21)、SSH(22)、Telnet(23)、HTTP(80)、HTTPS(443)
此外还有一些著名的端口号,如MySQL(3306)、Tomcat(8080)
2.动态端口号:1024-65535
问题:一个端口号可以被多个程序使用吗?不可以
一个程序可以拥有多个端口号吗?可以
两者的关系就像人和电话号码的关系
TCP协议
TCP编程:需要两个对象分别是客户端对象和服务器端对象,服务器端ServerSocket,客户端Socket;客户端通过new Socket(IP, Port)就可以连接到服务器端,服务器端调用accept()方法就可以得到客户端Socket对象。
TCP协议
:传输控制协议(Transmission Control Protocal),其协议格式可以表现为:
16位源端口号:表示数据从哪个进程中来
16位目的端口号:表示数据到哪个进程中去
32位序列号、32位确认序列号:为了满足全双工的安全机制而存在的。
4位的首部长度:表示TCP头部有多少个32位bit,即多少个字节,因而TCP头部最大长度为15*4=60
6个标志位:
- ①URG:紧急标志位,紧急指针是否有效
- ②ACK:确认号标志位,确认号是否有效
- ③PSH:推送标志位,提示接收端应用程序立刻从TCP缓冲区将数据读走
- ④RST:请求标志位,对方要求重新建立连接,把携带RST标识的称为复位报文段
- ⑤SYN:请求建立连接,把携带SYN标识的称为同步报文段
- ⑥FIN:通知对方本端要关闭连接了,我们把携带FIN标识的称为结束报文段
TCP十大特性:
1.确认应答ACK机制(保障TCP稳定的核心机制)
TCP将每个字节的数据都进行了编号. 即为序列号:
因为TCP会出现后发先制的情况,也就是说后面的消息比之前的消息先回应,消息之间的应答是不匹配的。
举例:A和B之间对话,A问有没有时间一起吃饭?要不要通个宵?B说不可能。好啊没问题。这个过程中B对A的回应或许出现了后发先制,B的意思可能是吃饭可以,通宵不可能。如何解决这个问题呢?
B可以针对A的问题加以标识,比如通宵不可能,吃饭没问题。但是这样会导致一个问题,在信息传递过程中占有太多的带宽。
所以有另外的一种解决方案:A在发送消息时携带同步序列号作为标志,B在回应消息时加上ACK(ACK为1)和确认序列号给A;我们知道TCP面向数据流,不是每个消息一个编号,而是每个字符一个编号,TCP对字节进行编号就成为了序列号,发送的时候是一个区间序列号,回应时的确认序列号是发送的最大序列号加1,表示可以继续发送下一段了。这样就解决了上面的问题。
确认应答可能带来的问题:
1.发送的数据报丢失
当发送数据丢失时,会一直对该数据进行重发,直到收到ACK为止。
2.确认应答丢失
当ACK丢失时,接收缓冲区不再写入重复数据!这是内核实现的去重
2.超时重传
超时重传的原因
:主机A向主机B发送数据时候因为网络堵塞丢失,数据丢失了;主机A未收到主机B的确认应答,ACK可能丢失了。出于这两种情况,主机A都会继续向主机B发送数据,直到获得主机B的ACK响应。存在的问题是,以相同的时间频率发送,必然是占用大量带宽的。
那么超时重传的时间如何确定呢?
- 策略1:不以固定的频率发送,策略1采取的是悲观的策略,如果第一次发送消息没有得到响应,大概率第二次也会发送失败,因此TCP以指数级时间频率发送消息。
第一超时重发时间间隔为500ms
,
第二次500ms2
第三次5002*2
。。。 - 策略2:经历了一定的超时重传次数后,如果消息还没得到应答,TCP认为网络或对端主机出现异常,强制关闭连接。
3.连接管理
TCP连接管理包含:
- 建立连接(3次握手)
- 关闭连接(4次挥手)
三次握手:
由于TCP是全双工通讯,在TCP通讯之前,首先要验证发送段与接收端的收发能力。如何验证呢?依赖的就是
三次握手机制
。
举个例子两个人打电话:A:hi咱们聊天吧,B:好的,你能听到吗,A:可以听到,开始吧。。。可以看出经过这三步就验证了两方的收发能力,此时就建立了TCP连接。
第一次连接:不能验证客户端与服务器端的收发能力
第二次连接:可以验证客户端的发送能力与服务器端的接收能力,但不能验证客户端的接收能力与服务器端的发送能力
第三次连接:可以验证验证客户端的接收能力与服务器端的发送能力
至此三次握手结束,TCP建立了连接,可以正常进行数据传输
二次握手建立连接行吗?
不可以!!!两次握手不能验证客户端的接收能力和服务器端的发送能力,因此这是不行的哦。
四次握手可以吗?
可以!!但是没必要,三次握手已经验证了二者的收发能力。
四次挥手:
当客户端与服务器端断开连接时,需要经历四次握手。举个例子:放学后,A:分手吧,B:好的,我收拾东西,B:我收拾好了,可以分手了,A:好的,分~可以看出经过这四步A和B就分开了。
三次挥手行吗?
有可能是可以的。比如B没有什么东西需要收拾,相当于经历了三次挥手就完成了整个分开的操作。`当接收缓冲区没有待结束的任务,两次挥手就可以合并成一次,这里用了TCP的捎带应答特性,就好比“好的,我知道,我收拾好了”。
三次握手、四次挥手示意图:
当服务器端new ServerSocket(port)时,服务端由closed状态变为listen状态,客户端new Socket(ip,port)时,客户端由closed状态变为syn_sent状态。
为什么TIME_WAIT的时间是2MSL呢?
- MSL是TCP报文的最大生存时间,2MSL为ACK的最大超时时间1MSL加上对方发送给他消息的一个最大等待时间1MSL
- 同时也是在理论上保证最后一个报文可靠到达(假设最后一个ACK丢失, 那么服务器会再重发一个FIN. 这时虽然客户端的进程不在了,
但是TCP连接还在, 仍然可以重发LAST_ACK - 也就是说,客户端害怕自己的消息服务端没有收到,也害怕服务端发送的消息自己没有收到,因此2MSL保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失(否则服务器立刻重启,可能会收到来自上一个进程的迟到的数据, 但是这种数据很可能是错误的)
一般而言,服务器上出现大量的 CLOSE_WAIT 状态, 原因是什么呢?
在程序中没有调用close()方法主动关闭连接!
4.滑动窗口
对于确认应答特性而言,没发送一个数据段,都要给一个ACK确认应答,当收到ACK后再发送下一个数据段,这样做的缺点就是性能比较差。
既然一发一收的性能比较低,那么我们可以一次发送多条数据,就可以提高性能,实际上将多个数据段的等待时间重叠在了一起。
- 滑动窗口大小:无需等待确认可以继续发送数据的最大值,对于下图而言滑动窗口大小为4000个字节(四个段)
- 发送前四个段时不需要等待ACK,直接发送
- 收到第一个ACK后,滑动窗口向后移动,继续发送第五个段数据
- 操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区记录哪些数据还没有被应答,只有确认应答过的数据才能发送缓冲区删掉 。
特别注意:
ACK=4001含义:告诉主机A已经成功收到了1-4000,而不是收到了3001-4000。
ACK返回的值是主机B接收缓冲区的下一个最大连续值,这称为“高速重发控制”或者“快重传”。
可能存在的两个问题:
1.消息已经发送过去,但是ACK丢失了。
①中间的ACK丢失:无关紧要,可以通过后续的ACK进行确认。
②最后一个ACK丢失:发送端重新发送最后一个数据段,接收缓冲区发现该数据已经存在,就将该段数据抛弃。
2.消息在发送的过程中丢失
比如1001-2000字节的报文丢失了,发送端会一直收到1001这样的ACK,就好像接收端在提醒发送端它想要1001,当发送端连续三次收到了1001应答,就会将1001-2000的数据重新发送;此时接收端收到1001之后,再返回就是最大的连续值了。因为2001之后的数据已经收到了,被放在了接收端操作系统的接收缓冲区中。
5.流量控制
以结果为导向(接收缓冲区的大小)为导向进行数据的传递。
TCP头部的16位窗口大小
:指的是接收缓冲区的窗口大小,而不是滑动窗口的大小;滑动窗口大小是固定,没有必要进行传递,接收缓冲区窗口大小是动态改变的;窗口大小通过ACK端通知发送端。- 当接收缓冲区满了,16位窗口大小为0,发送端将不会发送消息给接收端,但是会定期以固定频率发送窗口探测数据包;
- 接收缓冲区窗口大小不为0时,消息就会恢复发送。
- 16位最大表示65535,那么滑动窗口最大就是65536字节吗?答:不是的,TCP首部有一个窗口扩大因子,实际窗口大小是窗口字段值左移M位。
6.拥塞控制
尽管TCP有了滑动窗口特性,能够高效发送大量数据,但是如果一开始就发送大量的数据,仍然可能引发问题。比如网络已经很堵塞了,发送大量数据,肯定是有问题的。因此TCP引入了慢启动机制。
慢启动机制
:先发送少量的数据,摸清当前的网络拥堵状态,再去决定按照多大的速度传输数据。慢启动只是初始时慢,增长速度还是比较快的。而我们之前说的快重传指的是ACK返回的始终是数据连续的最大值。
图解拥塞控制:
- 引入一个“拥塞窗口概念”,刚开始定义拥塞窗口大小为1
- 拥塞控制窗口大小初始值为16,可以动态调整,开始发1个包,接着每次以指数形式增加包的数量,比如2、4、8、16。。。发送包数量大于拥塞窗口大小时,后面每次线性增长比如17、18。。。而不是指数增长了;当出现大量数据包丢失时,立刻将发送的包数量置为1,此外将拥塞窗口初始值设为当前丢包值的一半;然后接着重复执行上面的过程。。。。。。
- 每次发送数据包时候将拥塞窗口与接收端缓冲区窗口大小做比较,取较小的值作为实际发送的窗口。
拥塞控制, 归根结底是TCP协议想尽可能快的把数据传输给对方, 但是又要避免给网络造成太大压力的折中方案.
7.延迟应答
- 假设接收端缓冲区为1M. 一次收到了500K的数据; 如果立刻应答, 返回的窗口就是500K;
- 但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了;
- 在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来;
- 如果接收端稍微等一会再应答, 比如等待200ms再应答, 那么这个时候返回的窗口大小就是1M;
延迟应答策略:
- 时间限制:超过一个固定时间,延迟应答一次
- 数量限制:每隔N次发送延迟应答一次
- 需要注意的是:延迟应答时间一定要小于超时重传时间,通常来讲延迟应答是200ms;N一般取2。
8.捎带应答
捎带应答是针对于延迟应答的性能优化。
回顾三次挥手为什么具有可能性?
1.当接收端接收缓冲区没有任务时,可以将ACK与FIN合并成一次,因此可以三次挥手;
2.当接收缓冲区有任务时,利用延迟应答机制,等待接收缓冲区任务结束时,利用捎带应答机制,将将ACK与FIN合并在一起发送给发送端,实现了三次挥手。
9.面向字节流
由于TCP面向数据流,所以数据包没有边界;因此不知道发送的数据从哪里开始以及从哪里结束,可能会造成
沾包
和半包
问题。
10.沾包/半包问题
沾包和半包都是指得到的数据不是预期的数据。
沾包/半包示意图:
沾包解决方案1:以\n作为流的边界来处理沾包和半包问题;
解决方案2:每次按照固定大小读取数据包,这样能确定每个数据边界,就能正常收发消息了。
TCP异常情况
进程终止:进程终止会释放文件描述符,电脑系统还在运行,后台守护程序仍然可以发送FIN,和正常关闭没有什么区别。
机器重启:和进程终止的情况是相同的,仍然可以发送FIN。
机器掉电、网线断开:此时接收端认为连接存在,一旦接收端有写入操作,接收端发现连接已经不在了,就会进行reset;即使没有写入操作,TCP内置了一个保活定时器,会定期询问对方是否存在,如果对方不在就把连接释放掉。
TCP小结
保证稳定性:
- 确认应答机制
- 超时重传机制
- 连接管理
- 流量控制
- 拥塞控制
保证性能:
- 滑动窗口
- 延迟应答
- 捎带应答
UDP协议
基于UDP的应用层协议有那些?
动态主机配置协议(DHCP)
域名解析协议(DNS)
UDP报文格式:
UDP示意图:
报文信息解析:
16位UDP长度=UDP头部长度(8个字节)+ UDP数据长度,因而UDP一个数据报理论上最大长度位2的16次方,共65536=64kb
16位效验和:验证传输到目的主机的数据是否是正确的,在传输过程中是否被篡改过。
如何进行数据效验呢?原始的数据根据MD5算法进行计算
,会得到一个值,将这个值存储在16位的效验和当中;接收端接收到内容之后按照通过的规则加密数据得到一个效验和,将该效验和与UDP头部的16位校验和对比,如果相等数据就是正确的。
UDP编程时,如果数据大小超过64kb怎么办?
1.在应用层进行数据报的拆分和组合
2.大于64kb不进行处理,交给IP协议去处理,在网络层进行分包和组包(不用)原因:不稳定,在网络层分包后假如有包丢失,就会全部舍弃。
通信方式:
全双工:发送端和接收端既能发送消息又能接收消息;
半双工:发送端只能发送消息,接收端只能接收消息
怎么用UDP实现可靠的传输呢?(面试题)
可以参考TCP保证稳定的特性,比如:
引入序列号,保证数据传输的顺序;
引入确认应答,确保对端收到了数据;
引入超时重传,如果隔一段时间没有应答,就重新发送数据;
。。。。。。
二者区别
1.TCP是有连接的传输协议,而UDP是无连接的传输协议;
2.TCP传输是稳定的,而UDP传输是不稳定的;
3.TCP传输面向数据流,而UDP传输面向数据报;
4.TCP既有发送缓冲区也有接收缓冲区,而UDP只有接收缓冲区。例子:快递员把快递放到菜鸟驿站,而不是等一个一个人去取。
TCP与UDP的使用场景是不同的,对稳定性要求比较高时使用TCP,对消息丢失不敏感且要求性能高时,使用UDP。
4.网络层
网络层的作用就是在复杂的网络环境中确定一个合适的数据传输路径,为传输层进行服务。
基本概念:
- 主机:配有IP地址,但是不进行路由控制的设备
- 路由器:配有IP地址又能进行路由控制,每个路由器有路由映射表
- 节点:主机和路由器的统称
IP协议
IP协议格式:
IP协议格式参数说明
8位服务类型: 3位优先权字段已经弃用,4位TOS字段,和1位保留字段(必须设置位0);4位TOS分别表示为:最小延时,最大吞吐量,最高可靠性,最小成本,这四个相互冲突,只能选择一个,对于
ssh/telnet
这样的应用程序来说,最小延时比较重;对于ftp
这样的应用程序来说,最大吞吐量比较重要。
16位标识:表示分组ID
3位标志:保留、禁止分片、更多分片
;当3位标志位中最后1位设置1时,表示这个数据包是由多个包组成的。
13位片偏移:可能出现后发先制的问题,第2个包先过来然后第1个包才过来。根据偏移量可以知道每个包的顺序进行组包。
生存时间SSL:一般等于64,每经过一次路由器的跳转此值会减1,直到这个值为0,表示这是一个无效的路由地址,直接舍弃掉。举例:在浏览器中随便输入一个错误的地址,经过64次跳转后,是无法找到对应的服务器的。
8位协议:表示上层的传输层协议
16位首部校验和:检验当前传输过来的首部是否是正确的;由于传输层已经对数据进行了效验,因此网络不对数据进行效验,这样一来提高效率。
32位源IP地址/32位目的IP地址
IP协议包最小是20字节!!!
IP网段划分
目前IP版本有IPV4和IPV6两个版本
目前最流行的就是IPV4版本,采用点分四组十进制。每一组范围是[0~255],如:255.255.255.255
IP地址分为两个部分,网络号与主机号。
- 网络号:保证互相连接的两个网段具有不同的标识
- 在同一网段内,主机之间具有相同的网络号,但是主机号一定不能相同!
- 不同的子网实际上就是将网络号相同的主机放到了一起
如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号一定不能和子网中的其他主机的主机号重复!
IP地址可以分为五类:ABCDE
A类为:点分四组中的第一组地址范围为0~127的IP地址。已二进制来看就是“首位为0”
B类:128~191.二进制首位为10
C类:192~223.二进制首位为110
D类:224~239.二进制首位为1110
E类:240~255.二进制首位为1111
网络号:IP地址与子网掩码按位与得到的就是网络号转成10进制,这就是子网号
子网地址范围(内网取值范围):主机号从全0到全1就是子网的地址范围
子网地址范围计算:255 - 子网掩码最后一组的十进制值 + 网络号开始的值
IP地址和子网掩码还有一种简洁的表示方法,比如:140.252.20.68/24,IP地址为140.252.20.68/24,子网掩码的前24位是1,也就是说子网掩码为255.255.255.0
特殊的IP地址:
1.IP地址中的主机号都为0就成为网络号,代表这个局域网
2.IP地址中的主机地址都为1就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包
私有IP和公网IP:
10.**前8位是网络号,共16,777,216个地址
172.16.到172.31.,前12位是网络号,共1,048,576个地址
192.168.*,前16位是网络号,共65,536个地址
包含在这个范围中的, 都成为私有IP, 其余的则称为全局IP(或公网IP);
手动管理子网内的IP是非常麻烦的,因此:
有一种技术叫做DHCP,能够自动的给子网内新增加的主机节点分配IP地址,,避免手动管理IP不便性;
一般的路由器都带有DHCP功能,因此路由器也可以看作一个DHCP服务器
5.数据链路层
以太网
以太网不是一种具体的网络,而是一种技术标准,既包含了一些数据链路层的内容,也包含了一些物理层的内容。例如规定了网络拓扑结构,传输速率等;
以太网目前是最广泛的局域网技术,和以太网并行的还有令牌环网,无线LAN。
以太网帧格式:
源地址和目的地址是指网卡的硬件地址(也叫MAC地址), 长度是48位,是在网卡出厂时固化的;
帧协议类型字段有三种值,分别对应IP、ARP、RARP;
帧末尾是CRC校验码
。
数据链路层的MTU称为最大传输单元,共1500字节,他对UDP的影响:
当UDP携带的数据超过1500-8(UDP头部)-20(IP协议头部)=1472字节时,就会在网络层分成多个IP数据包。这就是UDP在数据链路层的大小限制。
MAC地址
- MAC地址用来识别数据链路层中相连的节点
- 长度为48位,也就是6个字节,一般用16进制数字加上冒号形式来表示,比如:08:00:27:03:fb:19
- 在网卡出厂时就已经确定了,不能修改,MAC地址通常是唯一的(虚拟机中的MAC地址不是真实的MAC地址)
MAC地址和IP地址的区别:
IP地址描述的是整个路途的起点和终点,而MAC地址描述的是每一个区间的起点和终点。
ARP协议
ARP协议不是单纯的数据链路层的协议,而是介于数据链路层与网络层之间的协议。
ARP作用:建立主机IP地址和MAC地址之间的映射关系
- 在网络通讯时,源主机的应用程序知道目的主机的IP地址和端口号,但是不知道目的主机的额硬件MAC地址;
- 数据包传输到对端时,先是被对端网卡接收再去处理上层协议的,如果接收到的数据包的硬件地址与本机不符合,直接抛弃;
- 因此在通讯之前必须获得目的主机的硬件地址。
6.网络传输流程
封装、分用示意图:
7.浏览器中输入一个url后会经历什么?
1.浏览器会先检查输入的url是否正确,检查是否符合http/https的规范;
2.浏览器检查此url浏览器中有没有缓存信息,如果有缓存,就会去拿缓存的信息;认为一般静态页面是不变的,可以通过强刷ctrl+r
解决或者在url中加上一个参数t表示timestamp去重新访问;
3.进行DNS域名解析,将url解析为ip地址,根据ip地址进行访问;
4.在传输层进行TCP3次握手(讲一下3次握手的内容传递以及两端状态变化);
5.HTTP协议request对象发送,它包含四部分内容:请求行,请求正文,空行和Body;
6.服务器端接收到请求,并进行相应的业务处理:①得到前端传递过来的参数②做参数非空效验以及相应的业务处理例如查询数据库;
7.服务器端把操作的结果返回给客户端;
8.浏览器拿到后端返回的结果兵调用浏览器的内核实现前端页面的渲染;
9.传输层进行TCP4次挥手(内容转换和状态变化),关闭TCP连接。