前言: 搞java开发的时候突然对网络产生了兴趣,兜兜转转最终还是再次学习起了大二时候经常不听课自学的网络原理.
参考视频是慕课网上的 一站式学习Java网络编程 全面理解BIO/NIO/AIO 第二章 与 剑指Java面试-Offer直通车 第二章.
目录
第一章 网络基础知识
1.1 七层网络协议
1.1.1 物理层
1.1.2 数据链路层
1.1.3 网络层
1.1.4 传输层
1.1.5 会话层
1.1.6 表示层
1.1.7 应用层
1.2 数据的变化
1.3 TCP/IP
第二章 TCP简介
2.1 TCP报文头部
2.2 三次握手
2.3 四次挥手
2.4 TCP与UDP的区别
2.4.1 TCP简介
2.4.2 区别
第三章 HTTP
3.1 简介
3.2 DNS解析过程
3.3 HTTP和HTTPS的区别
第四章 socket
当前市面上分别存在四层,五层,七层协议,而国际标准化组织iso制定的OSI七层协议模型是业界提出来的概念型框架,因此先来了解一下开放系统互连参考模型即OSI七层协议.
工程学科都是不断迭代的,因此七层协议大概是这么来的,
我们首先要解决两台物理机之间的通信需求,具体就是机器A向机器B发送比特流,机器B能收到这些比特流,这就是物理层要做的知识,物理层主要定义了物理设备的标准,如网线的类型,光纤的接口类型,各种传输介质的传输速率的,它的主要作用是传输比特流,即我们所谓的0101二进制数据将它们转化为电流强弱来进行传输,到达目的地后再转为0101的机器码,也就是我们常说的数模转换与模数转换.
现在我们可以进行数据的传输了,但是数据传输的可能是错的,不完整的,于是数据链路层应运而生,数据链路层定义了如何格式化数据以进行传输,以及如何控制对物理介质的访问,通常还提供错误检测与纠正.
本层将比特数据组成了帧,其中交换机工作在这一层,对帧解码,并对帧中包含的信息把数据发送到正确的接收方.
随着网络节点的不断增加,点对点通信时是需要经过多个节点的,那么如何选择最佳路径,变成了我们的首要需求,此时,便有了我们的网络层.
它的主要功能是将网络地址翻译成物理地址并决定如何将数据从发送方路由到接收方,网络层根据发送优先权,网络拥塞程度,服务质量以及可选路由的花费来决定从一个网络中节点A到另一个网络中节点B的最佳路径.
由于网络层处理并智能指导数据传送路由器并连接网络各段,所以路由器属于网络层,此层的数据我们称之为数据包,此层我们需要关注的协议主要是TCP/IP协议里的IP协议.
随着网络通信需求的进一步扩大,通信过程中需要发送大量的数据,如海量文件传输的可能需要很长时间,而网络在通信的过程中,会中断很多次,此时为了保证传输大量文件时的准确性,需要对发送的数据进行切分,切割为一个一个的段落,即segment进行发送.那么其中一个段落丢失了该怎么办,要不要重传,每个段落要按照顺序到达吗,这个便是传输层要考虑的问题了.
传输层解决了主机间的数据传输,数据传输可以是不同网络的,并且传输层解决了传输质量的问题,该层称之为OSI模型中最重要的一层,传输协议同时机型流量控制,或是基于接收方可接收数据的快慢程度规定适当的发送速率.
除此之外传输层按照网络能处理的最大尺寸,将较长的数据包进行强制分割,例如以太网无法接收大于1500字节的数据包,发送方节点的传输层将数据分割成较小的数据片,同时为每个数据片安排一个序列号,以便数据到达接收方节点的传输层时能以正确的顺序重组,该过程成为排序.
传输层需要关注的协议有TCP/IP中的IP协议与UDP协议.
现在我们已经保证给正确的计算机发送争取的封装过后的信息了,但是用户级别的体验好不好?难道我们每次都要调用TCP去打包,然后调用IP协议去找路由,自己去发?当然不行,所以我们要建立一个自动收发包,自动寻址的功能,于是发明了会话层,会话层的作用就是建立和管理应用程序之间的通信.
现在我能保证应用程序自动收发包和寻址了,但我要用linux给windows发包,两个系统语法不一致,就像exe不能在linux上运行一样,shell在windows下也是不能直接执行的,于是需要表示层,帮我们解决不同系统之间通信语法的问题,在表示层数据将按照网络能理解的方案进行格式化,这种格式化也因网络使用的类型不同而不同,
此时虽然发送方知道自己发送的是什么东西,转换成字节数组之后有多长,但接收方肯定不知道,所以应用层的网络协议诞生了,它规定发送方和接收方必须使用一个固定长度的消息头,消息头必须使用某种固定的组成,而且消息头里必须记录消息体的长度等一系列信息,以方便接收方正确的解析发送方发送的数据,应用层旨在让你更方便的应用从网络中接收到的数据,至于数据的传递,没有该层,也可以在两台电脑之间传递,只不过传来传去就是一堆1和0组成的字节数组.
该层需要我们重点关注的是与之相对应的TCP/IP协议中的HTTP协议.
从应用层开始,都会对要传输的数据头部进行处理,加上本层的一些信息,最终由物理层通过以太网电缆等介质将数据解析成比特流,在网络中传输,数据传递到目标地址,并自底而上将先前对应成的头部解析分离出来.
OSI是一个定义良好的协议规范集,并有许多可选部分完成类似的任务,它定义了开放系统的层次结构,层次之间的相互关系以及各层的可能的任务,是作为一个框架来协调和组织各层所提供的服务,但是OSI参考模型并没有提供一个实现的方法,而是描述了一些概念,用来协调进程间标准的制定.即OSI参考模型并不是一个标准,而是一个概念型框架.
事实的标准是TCP/IP四层架构参考模型,TCP/IP参考模型是首先由阿帕网所使用的体系结构,后来该结构被美国国防部用来做为计算机网络的标准,由于领头大哥的推动,市面上绝大多数厂商也以该标准为主用以商用,虽然TCP/IP协议并不完全符合OSI的七层参考模型,但我们依然可以理解为其是OSI的一种实现.
从字面上讲,有人可能以为TCP/IP协议是TCP与IP这两种协议,实际生活中有时确实就是指这两种协议,然后在很多情况下,它只是利用IP进行通信时所必须用到的协议群的统称,具体来说,IP,ICMP,TCP,UDP,Telnet,FTP,Http等等都属于TCP/IP协议,他们与TCP或ip的关系紧密,是互联网必不可少的组成部分,TCP/IP一词泛指这些协议,因此有时也称TCP/IP为网际协议群.
从图里我们可以看出TCP/IP与OSI在分层协议上稍有区别,TCP/IP中的应用层可以理解为约等于OSI中的应用层,表示层,会话层三层的组合,同时OSI的物理层和数据链路层在TCP/IP中被规定为链路层,OSI模型注重通信协议必要的功能是什么,而TCP/IP则更强调在计算机上实现协议应该开发哪种程序
下图中可以看出,和OSI一样,在数据的传输过程中,TCP/IP协议在传输过程中在每一层会对所发送的数据增加一个头部,在这个首部中,包含了该层必要的信息如发送的目标地址,以及协议相关信息.
我们都知道IP协议是无连接的通信协议,它不会占用两个正在通信的计算机之间的通信线路,这样IP就降低了对网络线路的需求,每条线可以满足很多不同的计算机之间的通信需要,通过IP,消息或者其它数据会被分割为较小的,独立的包,并通过因特网在计算机之间传送,IP负责将每个包路由至它的目的地,但IP没有做任何事情确认包是否按顺序发送,或者包是否被破坏,所以IP数据包是不可靠的,需要由它的上层协议来做出控制.
由TCP协议来进行控制,TCP简介:
源端口和目的端口各占两个字节,TCP和UDP都是不包含IP地址信息的,因为那是IP层要做的事.我们可以用ip地址+协议+端口号唯一标识网络中的一个进程,在一些场合也把这种唯一标识的模式称为套接字,也就是说虽然通信的重点是应用进程,但我们只要把应用的报文交到目的主机的某一个合适的端口,剩下的工作就由TCP来完成了.
swquence number是比较重要的序号,它占用了四个字节,TCP连接中,传送的字节流中的每个字节,都按顺序去编号的,例如一段报文的序号字段值是107,而携挟的数据共有100个字节,那么如果有下一个报文段,其序号就应该从100+107-207开始.
再往下是ack确认号,同样占四个字节,期望收到对方下一个报文第一个数据字节的序号,例如B收到了A发来的报文,其序列号字段是301,而数据长度是200字节,那表明B正确收到了A发送的到序号301+200-1=500为止的数据了.于是B期望收到A的下一个数据序号是501,于是B在发送给A的确认报文段中,会把ACK确认号置为501.
接下来就是我们的offset,即数据偏移,由于头部有可选字段,长度不固定,因此它指出TCP报文的数据距离TCP报文的起始距离有多远.
reserved是保留域,目前都是0.
TCP Flags是控制位,主要有八个标志位来组成,每个标志位表示一个控制功能.
ACK为1表示确认号有效,为0表示报文中不含确认信息,忽略确认号字段.
SYN同步序列号,在连接请求中,SYN等于1与ack等于0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认就是SYN等于1,ACK等于1.
FIN finish标志,用于释放连接,为1时表示发送方已经没有数据发送了.即要关闭数据流.
WINDOW窗口,即滑动窗口的大小,用来告知发送端接收端的缓存大小.以此控制发送端发送数据的速率.从而达到流量控制.
Checksum检验和,指的是奇偶校验,此校验和对整个的TCP报文段包括TCP头部和TCP数据以16位进行计算所得,由发送端计算和存储,由接收端进行验证.
Urgent Poniter紧急指针,只有当URG为1的时候才有效,指出本报文段中紧急数据的字节数.
TCP Options可选项,长度可变,定义一些其它的可选参数.
当应用程序希望通过TCP与另一个应用进行通信时,它会发一个通信请求,这个请求必须送到一个确切的地址,在双方握手之后,TCP将在两个应用之间建立一个全双工的通信,这个全双工的通信将占用两个计算机之间的通信线路,直到它被一方或双方关闭为止.
距离流程如下,图应该能看懂,网上也很多
为什么需要三次握手才能建立起连接?
主要是为了初始化Sequence Number的初始值,通信的双方要互相通知对方自己的初始化的Sequence Number.也就是上面的x和y,这两个要作为以后通讯的序号.以保证应用层接收到的数据不会因为网络上的传输问题而乱序,即TCP会用这个序号来拼接数据.因此在服务器回发它的Sequence Number即第二次握手之后,还需要发送确认报文给服务器告知服务器说客户端已经收到了你的初始化Sequence Number了.
四次挥手指的是终止TCP连接时,需要客户端和服务端总共发出四个包,以确认连接的断开.在socket编程中,这个过程由客户端和服务端任意一方执行close来触发.这里我们假设由客户端来主动触发close.四次挥手流程如下图所示
客户端发出的停止连接报文的序列号u,u表示前面establish状态下已经传送过来的数据的最后一个字节的序号加1.
小知识:
1.注意到四次挥手的过程中,从TIME-WAIT状态到CLOSED状态有一个超时设置,这个超时设置是2*MSL,那为什么需要等待这一段时间,不直接转换成close状态?
2.为什么需要四次挥手才能断开连接?
因为连接是全双工的,即数据可以在两个方向上进行传输,所以双方都需要FIN报文和ACK报文,所以发送与接收方各需要两挥手即可,只不过有一方是被动的,所以看上去就成了所谓的四次挥手.
3.服务器出现大量CLOSE_WAIT状态的原因
问题的其中一个表现是客户端一直在请求,但是返回给客户端的信息是异常的,服务端也压根没收到请求.
看上图只有一个原因,即收到对方的关闭请求后一直没有发送确认ACK报文.即
所以我们要:
4. 浏览器和服务器关闭TCP连接时间
根据Connection请求头,如果是keep-alive服务器就保持住tcp连接,如果没有或是close则服务器response传输完后主动关闭tcp连接。当然现在浏览器都是http1.1都默认是keep-alive的,在浏览器tab关闭时,tcp连接关闭。
5. 为什么握手是三次而挥手是四次?
这个是自己推断的,因为握手时,接收方接收到请求可以立即回复无影响,但是挥手时,接收方立即回复后还可能回发数据,所以要发第二次表明自己发送完了,发送方可以关了,那接收方收到断开连接请求时,不能不直接发送,等要发给接收方发完数据然后回复你可以关了,这样不就一次了,这样不行是因为发送方没收到确认收到消息会一直发送.
UDP头:
UDP 适用于在线媒体,多人广播,在线游戏
这个平时经常用很熟悉了,网上资料也很多,简要描述一下.
HTTP特点:
支持客户/服务器模式
简单快速.客户端向服务器请求服务的时候,只需要传送请求方法和路径,请求方法常用的有GET,HEAD,POST,每种方法规定了与服务器联系的类型不同,由于http协议简单,使得http程序的规模小,因而通信速度很快.
灵活.允许传输任意类型的对象,类型由content-type加以标记.
无连接.限制每次连接只处理一个请求,服务器处理完客户的请求,并收到客户的应答后即断开连接,采用这种方式可以节省传输时间.
从http1.1起默认使用了长连接,服务器需要等待一定时间后才断开连接,以保证连接效率.
无状态.意味着后续处理需要前段信息则必须被重传,这样可能导致每次传输的数据量增大.在服务器不需要先前应答时,它的速度就较快.
get请求与post请求的区别:
Cookie与Session的区别:
我们的域名其实是省略了root,比如如下,从右向左分别代表了不同层级,解析也是从右向左解析的.分层相当于为全网络的域名做了一个类似于索引的工作,当我们需要查找某一个特定的域名的时候,我们可以根据层级,以层层递进的方式找到我们需要的域名.
域名查找的两种方式:递归与迭代
递归查找:
根域名服务器找得到地址就把地址返回给DNS服务器,如果找不到根域名服务器就会去顶级域名找以此类推找到最后面的三级域名服务器,如果找到了就会一个个服务器返回.
迭代查询:
根域名找不到,把顶级域名的地址告诉DNS客户端,让DNS客户端去找,如果顶级域名服务器找不到地址,再重复上述的过程,直到找到域名的具体地址,由服务器返回给DNS客户端,再返回给浏览器.
在之前我们对网络数据的抓包中发现,用户的信息都裸奔在互联网上,容易被抓包然后暴露信息,或者伪造回复而不被客户端察觉(所谓的劫持).
要给数据裹上一层外套,人们便想到了加密.
非对称加密称加密用公钥进行加密,私钥进行解密.
常用的哈希算法有MD5等等.
数字签名就是在信息的后面加上一段内容,这些内容是经过哈希后的值,可以证明信息没有被修改过,哈希值一般都会加密后,也就是签名后,再和信息一起发送.以保证哈希值不被修改.
在使用的过程中人们发现,仅使用其中的某种加密方式并不能满足生产要求,要么非对称加密性能过低,要么对称密钥容易泄漏,因此https使用的是证书配合各种加密手段的方式.
HTTPS数据传输流程:HTTPS在进行传输之前,会与网站服务器和web浏览器进行一次握手,在握手时确定双方的加密密码信息.具体过程如下:
浏览器将支持的加密信息发送给服务器,如本地仅支持AES对称加密,ECC非对称加密.
服务器会依据浏览器提供的这一套支持的加密算法,在自己所提供的加密方式中,选出一套哈希算法和加密算法,将验证身份的信息以证书的形式发送回浏览器.证书的信息包含了发布证书的CA机构,证书的有效期,公钥,证书所有者,签名等等.CA机构是具备证书发布资格的权威机构,好比英语四六级委员会.
浏览器验证证书合法性,如果验证证书的有效性,则在浏览器地址栏会有标志显示,否则会显示不受信的标识.当证书受信后,web浏览器会随机生成一份密码,并使用证书中的公钥加密为A,之后就是使用约定好的哈希算法加密握手消息,生成B,并用刚才的密码对称加密B生成C,最后将它们回发给服务器.
服务器接收到浏览器发来的信息后,会使用网站本身的私钥将A解密得到随机生成的密码,通过密码解密浏览器发送过来的C,并验证解密后的值与B是否相等,如果相等,然后服务器会将经过哈希的握手信息D与加密后的D即E发送给浏览器.
客户端浏览器解密响应消息,并解密消息E,如果与服务器发送过来的D一致,则此握手过程结束后,服务器和浏览器会使用之前浏览器生成的随机密码和对称加密算法进行加密和交换数据.
注:握手信息就是三次握手的信息,要哈希主要是确保消息在传输过程中不被更改.
HTTP与HTTPS的区别:
ip层的ip地址可以唯一标识一台主机,TCP协议和端口可以唯一标识主机的一个进程.所以我们可以用ip地址+TCP协议+端口唯一标识网络中的一个进程.能够标识进程后就可以用socket进行通信了.
socket是对TCP/IP协议的抽象,是操作系统对外开放的接口.
socket起源于unix,而unix是遵从一切皆文件的哲学,socket是基于一种从打开到读和写再到关闭的模式去实现的,服务器和客户端各自维护一个文件,在建立连接打开后,可以向自己文件写入内容,供对方读取或者读取对方内容,在通讯结束时,会关闭文件.
个人理解:socket封装TCP/UDP的一些操作,所以可以用socket提供的api实现互联、传输数据等等.
具体API操作的流程: