三连四断

1.TCP连接的建立 (1)首先是服务器初始化的过程,从CLOSED(关闭)状态开始通过顺序调用SOCKET、BIND、LISTEN和ACCEPT原语创建Socket套接字,进入LISTEN(监听)状态,等待客户端的TCP传输连接请求。

(2)客户端最开始也是从CLOSED状态开始调用SOCKET原语创建新的Socket套接字,然后在需要再调用CONNECT原语,向服务器发送一个将SYN字段置1(表示此为同步数据段)的数据段(假设初始序号为i),主动打开端口,进入到SYNSENT(已发送连接请求,等待对方确认)状态。

TCP传输连接建立的三次握手过程

(3)服务器在收到来自客户端的SYN数据段后,发回一个SYN字段置1(表示此为同步数据段),ACK字段置1(表示此为确认数据段),ack(确认号)=i+1的应答数据段(假设初始序号为j),被动打开端口,进入到SYN
RCVD(已收到一个连接请求,但未进行确认)状态。这里要注意的是确认号是i+1,而不是i,表示服务器希望接收的下一下数据段序号为i+1。

(4)客户端在收到来自服务器的SYN+ACK数据段后,向服务器发送一个ACK=1(表示此为确认数据段),序号为i+1,ack=j+1的确认数据段,同时进入ESTABLISHED(连接建立)状态,建立单向连接。要注意的是,此时序号为i+1,确认号为j+1,表示客户端希望收到服务器的下一个数据段的序号j+1。

(5)服务器在收到客户端的ACK数据段后,进入ESTABLISHED状态,完成双向连接的建立。

双方同时主动连接的TCP连接建立过程

正常情况下,传输连接都是由一方主动发起的,但也有可能双方同时主动发起连接,此时就会发生连接碰撞,最终只有一个连接能够建立起来。因为所有连接都是由它们的端点进行标识的。如果第一个连接请求建立起一个由套接字(x,y)标识的连接,而第二个连接也建立了这样一个连接,那么在TCP实体内部只有一个套接字表项。

当出现同时发出连接请求时,则两端几乎在同时发送一个SYN字段置1的数据段,并进入SYN_SENT状态。当每一端收到SYN数据段时,状态变为SYN_RCVD,同时它们都再发送SYN字段置1,ACK字段置1的数据段,对收到的SYN数据段进行确认。当双方都收到对方的SYN+ACK数据段后,便都进入ESTABLISHED状态。图10-39显示了这种同时发起连接的连接过程,但最终建立的是一个TCP连接,而不是两个,这点要特别注意。


图 10-39
同时发起连接的TCP连接建立流程

从图中可以看出,一个双方同时打开的传输连接需要交换4数据段,比正常的传输连接建立所进行的三次握手多交换一个数据段。此外要注意的是,此时我们没有将任何一端称为客户或服务器,因为每一端既是客户又是服务器。

2.TCP连接的释放

在数据传输完毕之后,通信双方都可以发出释放连接的请求。释放连接的过程为如上图所示:

1)数据传输结束后,主机A的应用进程先向其TCP发出释放连接请求,不在发送数据。TCP通知对方要释放从A到B的连接,将发往主机B的TCP报文段首部的终止比特FIN置为1,序号u等于已传送数据的最后一个字节的序号加1。

2)主机B的TCP收到释放连接通知后发出确认,其序号为u+1,同时通知应用进程,这样A到B的连接就释放了,连接处于半关闭状态。主机B不在接受主机A发来的数据;但主机B还向A发送数据,主机A若正确接收数据仍需要发送确认。

3)在主机B向主机A的数据发送结束后,其应用进程就通知TCP释放连接。主机B发出的连接释放报文段必须将终止比特置为1,并使其序号w等于前面已经传送过的数据的最后一个字节的序号加 1,还必须重复上次已发送过的ACK=u+1。

4)主机A对主机B的连接释放报文段发出确认,将ACK置为1,ACK=w+1, seq=u+1。这样才把从B到A的反方向连接释放掉,主机A的TCP再向其应用进程报告,整个连接已经全部释放。

2. 双方主动关闭的TCP连接释放流程

与可以双方同时建立TCP传输连接一样,TCP传输连接关闭也可以由双方同时主动进行(正常情况下都是由一方发送第一个FIN数据段进行主动连接关闭,另一方被动接受连接关闭),如图10-41所示。具体描述如下:


  同时主动关闭TCP连接的流程

当两端对应的网络应用层进程同时调用CLOSE原语,发送FIN数据段执行关闭命令时,两端均从ESTABLISHED状态转变为FIN WAIT
1状态。任意一方收到对端发来的FIN数据段后,其状态均由FIN WAIT
1转变到CLOSING状态,并发送最后的ACK数据段。当收到最后的ACK数据段后,状态转变化TIME_WAIT,在等待2MSL后进入到
CLOSED状态,最终释放整个TCP传输连接。

3.注意的问题

  • 三次握手建立连接时,发送方再次发送确认的必要性
    • 主要是为了防止已失效的连接请求报文段突然又传到了B,因而产生错误。假定出现一种异常情况,即A发出的第一个连接请求报文段并没有丢失,而是在
      某些网络结点长时间滞留了,一直延迟到连接释放以后的某个时间才到达B,本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误认为是A
      又发出一次新的连接请求,于是就向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了,这样一直等待A发来数
      据,B的许多资源就这样白白浪费了。
    • 三次握手是连接两端正确同步的充要条件,因为TCP建
      立在不可靠的分组传输服务之上,报文可能丢失、延迟、重复和乱序,因此协议必须使用超时和重传机制。如果重传的连接请求和原先的连接请求在连接正在建立时
      到达,或者当一个连接已经建立、使用和结束之后,某个延迟的连接请求才到达,就会出现问题。采用三次握手协议就可以解决这些问题。如客户端发送的ACK数据段就是为了避免因网络延迟而导致的重复连接,因为这时客户端就可通过检查ACK数据段中的确认号就可得知该连接请求是否已失效。
  • 四次挥手释放连接时,等待2MSL的意义
    • 1)可靠地实现TCP全双工连接的终止       
      第一,为了保证A发送的最有一个ACK报文段能够到达B。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的B收不到对已发送的FIN和
      ACK报文段的确认。B会超时重传这个FIN和ACK报文段,而A就能在2MSL时间内收到这个重传的ACK+FIN报文段。接着A重传一次确认。在进行
      关闭连接四路握手协议时,最后的ACK是由主动关闭端发出的,如果这个最终的ACK丢失,服务器将重发最终的FIN,因此客户端必须维护状态信息允
      许它重发最终的ACK。如果不维持这个状态信息,那么客户端将响应RST分节,服务器将此分节解释成一个错误(在java中会抛出connection

      reset的SocketException)。因而,要实现TCP全双工连接的正常终止,必须处理终止序列四个分节中任何一个分节的丢失情况,主动关闭
      的客户端必须维持状态信息进入TIME_WAIT状态。

    • TCP分节可能由于路由器异常而“迷途”,在迷途期间,TCP发送端可能因确认超时而重发这个分节,迷途的分节在路由器修复后也会被送到最终目的地,这个
      原来的迷途分节就称为lost
      duplicate。在关闭一个TCP连接后,马上又重新建立起一个相同的IP地址和端口之间的TCP连接,后一个连接被称为前一个连接的化身
      (incarnation),那么有可能出现这种情况,前一个连接的迷途重复分组在前一个连接终止后出现,从而被误解成从属于新的化身。为了避免这个情
      况,TCP不允许处于TIME_WAIT状态的连接启动一个新的化身,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个TCP连接的时
      候,来自连接先前化身的重复分组已经在网络中消逝。
    • 短时间的多次请求可能会导致服务器上存在很多的TIME_WAIT,那么导致端口被用尽,无法继续访问应用程序。四次握手关闭也不是必须的,也可以通过套接字选项设置不需要关注TIME_WAIT状态。

4.TCP的有限状态机

连接的建立和释放所要求的步骤可以用一个有限状态机来表达,该状态机有11种状态。每一种状态中都存在一些合法的事件,当合法事件发生的时候,可能需要采取某个动作。当其他事件发生的时候,则报告一个错误。


状 态


描 述


CLOSED


关闭状态,没有连接活动或正在进行


LISTEN


监听状态,服务器正在等待连接进入


SYN RCVD


收到一个连接请求,尚未确认


SYN SENT


已经发出连接请求,等待确认


ESTABLISHED


连接建立,正常数据传输状态


FIN WAIT 1


(主动关闭)已经发送关闭请求,等待确认


FIN WAIT 2


(主动关闭)收到对方关闭确认,等待对方关闭请求


TIMED WAIT


完成双向关闭,等待所有分组死掉


CLOSING


双方同时尝试关闭,等待对方确认


CLOSE WAIT


(被动关闭)收到对方关闭请求,已经确认


LAST ACK


(被动关闭)等待最后一个关闭确认,并等待所有分组死掉

TCP建立与释放的变迁如图所示:

    • 客户进程变迁的过程(粗实线)
      • 连接建立:设一个主机的客户进程发起连接请求(主动打开),这时本地TCP实体就创建传输控制快(TCB),发送一个SYN为1的报文,进入
        SYN_SENT状态。当收到来自进程的SYN和ACK时,TCP就发送出三次握手中的最后一个ACK,进而进入连接已经建立的状态
        ESTABLISHED。
      • 连接释放:设运行客户进程主机本地TCP实体发送一个FIN置为1的报文,等待着确认ACK的到达,此时状态
        变为FIN_WAIT_1。当运行客户进程主机收到确认ACK时,则一个方向的连接已经关闭。状态变成FIN_WAIT_2。当运行客户进程的主机收到运
        行服务器进程的主机发送的FIN置为1的报文后,应响应确认ACK时,这是另一个连接关闭。但此时TCP还要等待一段时间后才删除原来建立的连接记录。返
        回到初始的CLOSED状态,这是为了保证原来连接上的所有分组都从网络中消失了。
    • 服务器进程变迁的过程(粗虚线)
      • 连接建立:服务器进程发出被动打开,进入监听状态LISTEN。当收到SYN置为1的连接请求报文后,发送确认ACK,并且报文中的SYN也置为1,然后进入SYN_RCVD状态。在收到三次握手最后一个确认ACK时,就转为ESTABLISHED状态。

      • 接释放:当客户进程的数据已经传送完毕。就发出FIN置为1的报文给服务器进程,进入CLOSE_WAIT状态。服务器进程发送FIN报文段给客户进程,
        状态变为LAST_ACK状态。当收到客户进程的ACK时,服务器进程就释放连接。删除连接记录。回到原来的CLOSED状态
时间: 2024-11-05 23:29:05

三连四断的相关文章

求助-俄罗斯[结]

zjmnns晨冶昂匮断趁<http://weibo.com/p424p711p/230927983106224021053440?s420180411> e1m8xw却偷梁研辰头<http://weibo.com/mOZp/230927983096321688739840> tlk2yx睬屏速稳炒朔<http://weibo.com/p421p699p/230927983128491593568256?B420180411> rqsg31岸笔挤古趁耗<http:/

tcp 三次握手和四次断连深入分析:连接状态和socket API的关系

说到tcp协议,凡是略微看过的人都能顺口说出三次握手和四次断连.再牛逼的一点的就能够把每一个状态(SYNC_SENT.CLOSE_WAIT. ... ..等)都能背出来, 而说道socket编程.基本上写过网络编程的人都会熟悉那几个标准的API:socket.connect.listen.accept.... ..等 可是.我敢打赌非常少有人明确tcp状态和socket编程API之间的关系.不信? 看看例如以下几个问题你是否知道吧: 1)什么时候客户端才干够连接上server端, 是server

基于NIO的消息路由的实现(四) 服务端通讯主线程(2)断包和粘包的处理

本来我打算单独开一章,专门说明粘包和断包,但是觉得这个事儿我在做的时候挺头疼的,但是对于别人或许不那么重要,于是就在这里写吧. 那么何谓粘包.何谓断包呢? 粘包:我们知道客户端在写入报文给服务端的时候,首先要将需要写入的内容写入Buffer,以ByteBuffer为例,如果你Buffer定义的足够大,并且你发送的报文足够快,此时就会产生粘包现象,举例来说 你发送一个 报文" M|A",然后你有发送了一个"M|B",如果产生粘包,服务端从缓冲区里面读出的就是"

NIO框架之MINA源码解析(四):粘包与断包处理及编码与解码

1.粘包与段包 粘包:指TCP协议中,发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾.造成的可能原因: 发送端需要等缓冲区满才发送出去,造成粘包 接收方不及时接收缓冲区的包,造成多个包接收 断包:也就是数据不全,比如包太大,就把包分解成多个小包,多次发送,导致每次接收数据都不全. 2.消息传输的格式 消息长度+消息头+消息体  即前N个字节用于存储消息的长度,用于判断当前消息什么时候结束. 消息头+消息体    即固定长度的消息,前几个字节为消息

TCP协议三次握手连接四次握手断开和DOS攻击

转载:http://blog.csdn.net/fw0124/article/details/7452695 TCP连接的状态图 TCP建立连接的三次握手过程,以及关闭连接的四次握手过程 贴一个telnet建立连接,断开连接的使用wireshark捕获的packet截图. 1.建立连接协议(三次握手)(1)客户 端发送一个带SYN标志的TCP报文到服务器.这是三次握手过程中的报文1.(2) 服务器端回应客户端的,这是三次握手中的第2个报文,这个报文同时带ACK标志和SYN标志.因此它表示对刚才客

spring cloud: Hystrix(四):feign类似于hystrix的断容器功能

spring cloud: Hystrix(四):feign使用hystrix @FeignClient支持回退的概念:fallback方法,这里有点类似于:@HystrixCommand(fallbackMethod = "notfindback")的fallbackMethod 方法. fallback方法调用的是一个类.,feign也有:/health, /health.stream地址信息 http://192.168.1.4:7601/health 1.首先要在配置件开启hy

《梦断代码》第四阶段阅读感想(包括第9、10、11共三章)

第9章 方法   经过两年多的工作,OSAF开始有了固定的工作流程,还有了一套可能让它朝 目标行进的可行的方法论.最早要做好现实的计划和进度安排,但是成功的流程难以捉摸, 没有任何一种方法论能够覆盖软件项目的广大领域,但是结构化编程.改进组织代码的方式仍然 是有利于工作进程.    在团队项目开发中,虽然由于个人或者团体的原因会使原定的计划产生偏差,但是还是避免 了重新定制计划所带来的缓慢.延误,所以制定一个合理的计划并努力遵循它还是必然的. 第10章 工程师和艺术家 “软件”与“工程”密不可分

springcloud 的学习(四) 断路由

滴水穿石 添加依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> ribbon + restTample 启动类添加注解 : @EnableHystrix service 类上添加一个回滚的方法 当服务不可用的时候,直接调用回滚的方

TCP连接除了四次挥手断开外,还有什么断开连接的方式?

如果主机需要尽快关闭连接(或连接超时,或端口.主机不可达)时,发送RST包(RST表示复位)强制关闭TCP连接. 发送RST包关闭连接时,可以丢弃缓存区的包直接发送RST包,而接收端收到RST包后,也不必发送ACK包来确认.