分布式基础-网络通信协议讲解
-
网络七层协议模型
OSI的体系结构:应用层用来跑应用程序的。7层是指OSI七层协议模型,主要是:应用层(Application),表示层(Presentation),会话层(Session),传输层(Transport),网络层(Network),数据链路层(DataLink),物理层(Physical)。
OSI的七层协议可以变成TCP/IP的四层协议,四层协议就是把应用层,表示层,会话层合为一层称之为应用层,在这一层里面有三个重要的协议:TELNET(通过端口进行数据的连通的),FTP协议,SMTP协议。然后运输层,在4层也好还是5层也好,都没有变,在4层里面最主要关心的是TCP或者是UDP。在四层的模型中运输层中的TCP或者UDP是通过网际层 IP来进行延展的,不管TCP或者UDP通信也好,都是走的是下层协议。相当于一层一层的往下包装,把它包装成一个能够与底层交互的模型,然后通过这个模型在网络中进行传输,这个模型称之为报文/数据包。我们主要关心的是四层协议,在四层协议中主要关心的是运输层和网际层。FTP:文件传输协议 。SSH:远程登录协议。HTTP:无状态的协议。这三种协议都属于高级协议,是依赖于底层的协议包装出来的一个新得协议出来的。下面的会话层有点类似于javaWeb中的session,通过会话来保持状态的。在传输层就是TCP/UDP:MAC地址(在机器的网卡里面是唯一的)+IP地址+端口号(主要的作用是监听和怎么连接到服务端),在写网络编程的时候,这三个是不可缺少的,IP地址加上端口号是唯一的标识。TCP:是一个长连接(控制传输协议),是一个可靠性的协议(因为里面有一个滑动窗口协议),代表 一定能到达对面的服务端或者是客户端的,传输过程中是不能断开的。UDP:是一种数据包的传输协议,是允许中间断网,断开连接之类的,允许数据丢失的,比如看电影,聊天都是使用了UDP的协议。TCP的数据传输过程:发送端每一层都增加了首部,以太网的首部用来和外网进行通信的,只要知道IP地址,就可以与它建立起连接。在发送端都包装完之后还不能够发送给客户端,需要序列化为二进制的方式给它发送到客户端去,接收端是每接受一层就删除一层首部。包装的目的是能够在网络中去传输数据。
-
UDP数据传输过程
都是进行一次一次的包装。如果不包装是无法通过以太网在链路层进行传输的。需要符合它的格式和标准,如果不符合的话 它是传播不过去的。TCP/IP分层模型的分层以太网上传输UDP数据包如图所示: -
协议之间的联系
总共也是分四层,这里总共有四个应用程序,双箭头代表两个之间可以相互通信和联系的,应用程序可以直接访问ICMP协议(Inter的控制报文协议来对数据传输的),应用程序可以通过UDP和TCP的方式来传输到IP的这一层。网络层就是IP,不管是控制报文协议,或者是控制组协议,这两个协议都是基于IP的,所以说不管怎么玩都是加首部的。链路层就涉及到了以太网,有两个协议,地址解析协议:ARP,反向地址解析协议:RARP,不管怎么解析都是基于以太网的网卡的接口的来做一个扩展和解析的,然后通过以太网和物理传输介质去传输到其他的服务端和客户端。所以说整个的执行过程中就是上面的过程。在这些的协议当中用的最多的是传输层的TCP/UDP,和应用层的HTTP协议,FTP协议。图像的传输和邮件的传输都可以用UDP来传,如果是一个 可靠性数据的传输需要用到tcp。 -
TCP的三次握手和四次挥手
第一次握手:主机A发送位码为syn=1,随机产生seq number=x的数据包到服务器,客户端进入SYNSEND状态,等待服务器的确认;主机B由SYN=1知道,A要求建立联机;第二次握手:主机B收到请求后要确认联机信息,向A发送ack number(主机A的seq+1),syn=1,ack=1,随机产生seq=y的包,此时服务器进入SYNRECV状态;server是被动的被打开。第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。客户端和服务器端都进入ESTABLISHED状
态,完成TCP三次握手。TCP位码,有6种标示:SYN(synchronous建立连接) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急)
Sequence number(顺序号码) Acknowledge number(确认号码)单工:数据传输只支持数据在一个方向上传输
半双工:数据传输允许数据在两个方向上传输,但是在某一时刻,只允许在一个方向上传输,实际上有点像切换方向的单工通信
全双工:数据通信允许数据同时在两个方向上传输,因此全双工是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力 -
四次挥手
第一次挥手:主机1(可是使客户端,也可以是服务器端),设置Sequence Number和Acknowledgment Number,向主机2发送一个FIN报文段;此时,主机1进入FINWAIT1状态;这表示主机1没有数据要发送给主机2了
第二次挥手:主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknowledgment Number为Sequence Number加1;主机1进入FINWAIT2状态;主机2告诉主机1,我也没有数据要发送了,可以进行关闭连接了
第三次挥手:主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入CLOSEWAIT状态;第四次挥手:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIMEWAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。
由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭 -
TCP通信原理
首先,对于TCP通信来说,每个TCP Socket的内核中都有一个发送缓冲区和一个接收缓冲区,TCP的全双工的工作模式及TCP的滑动窗口就是依赖于这两个独立的Buffer和该Buffer的填充状态来进行处理的。接收缓冲区把数据缓存到内核,若应用进程一直没有调用Socket的read方法进行读取,那么该数据会一直被缓存在接收缓冲区内。不管进程是否读取Socket,对端发来的数据都会经过内核接收并缓存到Socket的内核接收缓冲区,发送端把数据发送到发送缓冲区内了,那么数据会一直在缓冲区中,它不会消失,除非把电脑关掉。TCP发送缓冲区是在内核里面的,这也就是在io流操作的时候,当有数据的写入的时候用flush方法:清空内核中缓冲区的数据,如果不清空的话可能导致一些问题,因为里面写满了,在也写不了了。read所要做的工作,就是把内核接收缓冲区中的数据复制到应用层用户的Buffer里。进程调用Socket的send发送数据的时候,一般情况下是讲数据从应用层用户的Buffer里复制到Socket的内核发送缓冲区,然后send就会在上层返回。换句话说,send返回时,数据不一定会被发送到对端。缓冲区的大小是在内核中的是固定大小的,比如32位的长度。发送端的数据往TCP发送缓冲区中发送数据,发送到一定程度,就会把TCP发送缓冲区给沾满,占满以后再发送的话,现在发不进去的话去等待接收端把TCP接收的缓冲区中的数据给拿出来,拿出多少,发送缓冲区就存多少,这里就会出现阻塞的状态:代表TCP缓冲区的数据满的话,还想放数据的话是不行的,是需要等待的。在传输过程中有三种流:BIO(同步阻塞IO流):不会通知线程。NIO(同步非阻塞IO流):高性能的流。有一个告诉的通道:socketChannel对象
这个对象有一个事件的机制,如果多的话,线程会挂起,如果有空闲的话,会通知线程
AIO(异步非阻塞IO流):期间可以做其他事情。
-
TCP通信的执行流程
用网络编程socket(套接字),好比一个接口,能够把两端连接起来,来进行通信,进行协作的。刚开始服务端启动,做了一个绑定到某个端口上面去,然后去监听端口,然后accept的时候就阻塞了。直到等到客户端来进行连接刚刚被监听的端口,然后这个TCP的连接被被动的打开,在建立连接的时候就有三次握手,然后在服务端就有读和写的操作了。可以在缓冲区里面读,也可以在缓冲区里写,客户端关闭的话,服务端还可以在缓冲区里面读。如何保证发送的和HTTP报文是一样的。这里有一个协议:滑动窗口-主要用来限流的,保证数据能够到对端,并且对端确定数据已经到达的,这时它才会执行滑动窗口。
欢迎各位小伙伴来咨询,想要工程源码的加群:797853299