java网络通信:TCP协议
Posted Wellhold
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java网络通信:TCP协议相关的知识,希望对你有一定的参考价值。
面试的时候,面试官由于需要考察一个面试人对于网络编程的熟悉程度,往往会考察学生对于TCP、HTTP、UDP、这些常见的网络编程当中的协议的了解程度,而TCP协议则是首当其冲的,作为进程之间通信常用的一种协议,只要岗位涉及到了进程之间的相互通信,则一定会被询问到TCP协议,那么本篇就来总结一下TCP协议吧~
TCP协议在OSI七层模型当中,是属于传输层的协议,它是一种可靠传输的协议,这个可靠,指的是TCP可以确保通信信息不会因为网络因素导致丢包,确保接受方一定可以接受到完整的数据。在TCP可靠传输方面,常常与另一个协议——UDP协议进行对比,我们通过两者的对比,先大体对TCP协议有些了解。
1.TCP和UDP的异同点
1)tcp是面向连接的,而udp则是不需要建立连接的。
2)tcp是面向字节流的,而udp则是面向数据报的。这话的理解是udp发送的报文长度是进程给出的,而TCP发送的报文长度,则是根据对方的接受窗口和当前网络的情况决定的。可以想象TCP是按流传输,而udp是按一个一个报文进行传输的。
3)tcp是可靠传输,而udp是尽最大可能交付的协议,tcp的可靠传输主要是通过滑动窗口和发送-确认-窗口滑动机制,来确保的,而udp就是尽可能发送,不确保发送的数据是否到达的。
4)tcp是一对一的全双工的通信,而udp可以一对一,一对多,多对一,多对多的通信。
5)tcp具有流量控制,拥塞控制机制,而udp没有。
从上述的比较,可以大体把握了TCP是一个什么样的协议,那么接下来,我们来看看在面试当中涉及到TCP协议的话,必要考的一个考点,TCP的三次握手和四次挥手。
2.TCP的三次握手和四次挥手
tcp是面向连接的协议,那么两个进程需要通过tcp进行交互的时候,需要首先建立连接,这个建立连接的过程,需要来回三次通信,所以顾名思义,被较为了三次握手,那么这三次握手是一个什么样的流程?首先我们来看一下图。
在图中,着重关注几个点,Client和Server的状态变化、标志位的置1、发送序号的数字。
首先我们要发起连接请求的进程称之为Client,而被动接收连接请求的称之为Server,Server和Client在发起连接请求之前,都会创建TBC(传输控制块),这时候Server将进入监听(Listen)状态,而Client建立TCB之后,将发送连接请求。
Client将要发送的TCP报文当中的SYN标志位置1,并且在发送序号置为了x,发送到Server,这时候Client将进入SYN_SENT(同步已发送)状态。
Server接收到后,向Client回复一个SYN标志位也置1,ACK标志位置1,发送序号为:y,而确认序号为:x+1 的tcp报文,这时候Server将进入SYN_RCVD(同步接收)状态
Client接收到Server的回复报文之后,再回复一个ACK标志位置1,发送序号为x+1,确认序号为:y+1 的tcp报文,这时候Client和Server都同时进入ESTABLISH状态,连接建立。
想面试官讲解完三次握手之后,面试官可能会问出一个常规的延伸问题,为什么是三次握手,而不是两次握手呢?
这是为了防止Client已失效的连接请求报文突然又传到了Server,产生错误。举个例子详细来说,Client发送连接请求,但是因为连接请求的报文丢失而未收到确认,于是Client又一次重传了一次连接请求,后来收到了确认,然后建立了连接,数据传输完毕后,释放了连接。而第一个连接请求这时候到达了Server,Server收到了报文之后,误认为Client需要再次建立连接,就会回复这个连接请求,而这时候由于实际上Client这时候并没有发起请求,所以Client会忽略这个回复,而如果采用的是两次握手,这时候Server就已经进入建立连接的状态,白白的浪费了资源。而采用三次握手,Server就不会收到回复,则就表明这是一个无效的连接,就会中断。
3.TCP的四次挥手
因为tcp是一个全双工的协议,所以为了确保连接的安全断开,在tcp协议当中,采用的是四次挥手的方式断开连接,那么这四次挥手又都伴随着什么要的标志位变化和状态变化呢?先看下图:
首先是Client停止发送数据,并向Server发送一个FIN位置1,发送序号为:u 的tcp报文,并且这时候Client进入FIN-WAIT-1(终止等待1)状态。
Server在接收到连接释放报文之后,回复一个确认报文,这个报文的ACK位置1,发送序号:V,确认序号:u+1,这时候Server就进入了CLOSE-WAIT(等待关闭状态),而Client进入FIN-WAIT-2状态,这时候从Client到Server这个方向的连接就被断开了,但是注意,这时候TCP连接还处于“半关闭”状态,因为这时候Server可能还有需要向Client发送的数据,Client还能继续接受,这个状态会持续到Server把需要发送的数据发送完全。
Server把需要发送的数据发送完全后,向Client发送一个连接释放报文,这时候一定要注意这几个序号和位的变化,这个报文的FIN位置1,ACK位置1,发送序号为:w,并且确认序号还是:u+1。并且Server进入了LAST-ACK(最后确认)状态。
Client接收到这个连接释放请求之后,回复一个ACK置1,确认序号:w+1,发送序号:u+1的报文回复。并且进入TIME-WAIT状态,而Server在接受到这个回复以后,进入Closed状态。
Client在进入到TIME-WAIT状态等待2MSL之后,就也会进入关闭状态。
当面试的人描述到这里,这时候面试官肯定又会问一个常规的延伸问题:为什么客户端在回复服务器的断开请求的时候,需要进入TIME-WAIT状态,并且等待两个MSL(最长报文寿命),而不是直接CLOSED呢?
第一、为了确保Client在回复Server的连接断开请求的时候,最后一个ACK报文能够到达Server,因为这个报文有可能会丢失,而Server在没有接受到Client回复的报文的时候,会超时重传连接释放请求,这时候Client出于TIME-WAIT状态,就可以接收到这个重传的请求,如果没有TIME-WAIT状态,则这时候会导致Server永远都处于重传的状态,无法Closed。
第二、防止已失效的连接请求报文出现在本连接当中,Client在发送完最后一个ACK报文之后,经过了两个MSL,就可以使本连接持续时间内所有产生的所有报文都从网络消失,这也是为什么定了两个MSL的原因。
最后附上tcp的六种标志位:
URG 紧急指针,告诉接收TCP模块紧要指针域指着紧要数据。
ACK 置1时表示确认号(为合法,为0的时候表示数据段不包含确认信息,确认号被忽略。
PSH 置1时请求的数据段在接收方得到后就可直接送到应用程序,而不必等到缓冲区满时才传送。
RST 置1时重建连接。如果接收到RST位时候,通常发生了某些错误。
SYN 置1时用来发起一个连接。
FIN 置1时表示发端完成发送任务。用来释放连接,表明发送方已经没有数据发送了。
其中URG不能和PSH标志位同时使用
以上是关于java网络通信:TCP协议的主要内容,如果未能解决你的问题,请参考以下文章