tcp建立连接

tcp连接的建立需要经历”三次握手“的过程。过程如下

  1. client发送SYN包(值为j)以及SEQ包到server端,此时client进入SYN_SEND状态。此为第一次握手。
  2. server端收到SYN包后,发送一个ACK(值为seq+1)确认包和SYN(值为k)给client,此时server进入SYN_RECV状态。此为第二次握手。
  3. client收到SYN+ACK包后,向server发送一个ACK(值为k+1),该包发送完成后,client和server均进入ESTABLISH状态。此为第三次握手。

client和server两端状态变化如下:

client:
CLOSED->SYN_SEND->ESTABLISH
server:
CLOSED->LISTEN->SYN_RECV->ESTABLISH

为什么是3次握手,不是2次或者4次呢?

建立一个可靠的tcp连接,至少是要3次的,既然3次就足够,为什么还要4次。
那2次可以么。假设2次就建立连接,那么会出现如下情况。
client发送一个A请求,由于网络原因,没有那么快送达server端。此时client便废弃该请求,重新发起请求B,请求B成功送达server端,并得到响应。
如果此时便建立连接,若之前的请求A终于到达server端了,由于请求的格式都是正常的,于是也发送响应回去client,而client则认为该请求已经被废弃。于是server端就一直挂着这个请求,造成资源浪费。

因此,才需要让client再发送一次确认给server端,server接收确认后才建立连接,便可以避免这种情况了。

tcp连接释放

Tcp释放连接的过程需要经历“四次挥手”的过程,为什么建立连接只需要3次握手,而释放连接需要进行4次挥手呢?

很简单,因为TCP连接是全双工(Full Duplex)的,因此造成了两个方向都需要进行关闭。

怎么理解呢?

client和server,需要关闭连接,此时client通知server我要关闭连接了,此时关闭的只会是client这一端的连接,而server端并未关闭,它依旧能够向client发送数据。

当然,关闭连接也可以是server作为主动方的。

接下来以client主动断开与server端的连接为场景来描述整个过程,我们把它分为两个阶段,分别为client端关闭连接和server端关闭连接。

先上图

第一阶段

  1. 首先client会发送一个FIN包给server(同时还有ack和seq包),这是要告诉server,我已经没有数据要发给你了,此时client处于FIN_WAIT_1状态。接收到FIN包的server处于CLOSE_WAIT的状态。
  2. server发回一个ACK(值为client传过来的seq+1)和seq(值为client传过来的ack的值)给client。client收到server发过来的包后确认关闭连接,此时client处于FIN_WAIT_2。

第二阶段

  1. server在接收到client的FIN后,得知client要断开tcp连接了,于是在发送完ack和seq给client后,自己发送一个FIN包给client(也带有ack和seq包),告诉client我也要断开连接了,此时server处于LAST_ACK状态。
  2. client接收到server的FIN信息后,会回复server一个ack包,并且会进入TIME_WAIT状态,持续2个MSL(Max Segment Lifetime),这个时间windows下为240s。而server接收到client后便关闭连接。client在指定时间过后仍然没有接收到server的数据,确认server已经没有数据过来,也关闭了连接。

此时双方都进入CLOSED状态。

分析一下

server在接收到client的FIN后,会返回ACK给client,此时关闭的就是读通道,也就是说不能再从这个连接中读信息了。

client收到server发送过来的对自己的FIN的确认包ack后,便关闭了写通道,不能再向连接中写信息了。

server也开始关闭连接,发送FIN给client,而client收到后便回复ack给server,同时关闭读通道,自己则进入TIME_WAIT状态。

server收到client发送过来的对自己的FIN的确认包ack后,便关闭了写通道,状态转化为CLOSED。

而client在TIME_WAIT结束后也进入CLOSED状态。

因此client和server会经历如下状态的转移
client:
FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
server:
CLOSE_WAIT->LAST_ACK->CLOSED

其中有几个关键点需要注意:

  1. 这个TIME_WAIT的作用是什么?
    这个博客是这么解释的。

    1. 原因有二:
    2. 一、保证TCP协议的全双工连接能够可靠关闭
    3. 二、保证这次连接的重复数据段从网络中消失
    4. 先说第一点,如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN
    5. 此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACKServer就会以为是连接错误把问题报告给高层。
    6. 这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。
    7. 所以,Client不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。
    8. 再说第二点,如果Client直接CLOSED,然后又再向Server发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。
    9. 一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依据是socket pair
    10. 于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2MSL,这样可以保证本次连接的所有数据都从网络中消失。
  2. CLOSE_WAIT的解释。
    在以上事例,我们知道server在接收到FIN后,发送ACK之前会进入CLOSE_WAIT,如果长期处于这个状态,或者说服务器出现大量CLOSE_WAIT,说明ACK包一直没有发出,这时候就应该检查代码了。

  3. TIME_WAIT注意事项
    从事例我们知道,主动关闭连接的一方会经历TIME_WAIT状态,在该状态下的socket是不会被回收的。而如果是服务器端主动关闭连接,则可能会面临处于大量TIME_WAIT的情况(因为连接很多嘛),会严重影响服务器的处理能力。
    怎么解决呢,那就减少服务器端TIME_WAIT的时间咯。

综上所述,client和server从建立连接到断开连接,整个状态的变化如下:

client:
CLOSED->SYN_SEND->ESTABLISH->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
server:
CLOSED->LISTEN->SYN_RECV->ESTABLISH->CLOSE_WAIT->LAST_ACK->CLOSED

websocket

tcp是传输层的协议,tcp三次握手后,应用层协议http也便建立了连接。而对于当今web的发展情况,http仍有许多瓶颈。

  1. 一条连接只能发送一个请求。
  2. 请求只能从客户端开始。客户端不可以接收除响应以外的指令。
  3. 请求/响应首部未经压缩发送,首部信息越多延迟越大。
  4. 发送冗长的首部。每次互相发送相同的首部造成较多的浪费。
  5. 可任意选择数据压缩格式。非强制压缩发送。

虽然已经出现了很多解决方案,如ajax、comet,但是他们最终使用的都是http协议,因此也无法从根本上解决这些瓶颈。
因此也就诞生了一个新的通信协议,WebSocket协议,一种全双工通信协议。

该通信协议建立在http协议的基础之上,因此连接的发起方仍然是客户端,在http连接建立之后,再将协议升级为webSocket连接,在webSocket连接建立之后,客户度和服务器端都可以主动向对方发送报文信息了。

建立webSocket连接,需要先建立http连接,并在此基础上再进行一次”握手“。

client会发起一个”握手“的请求,请求首部含有upgrade:websocket(还有其他首部,具体看如下示例)。服务器端返回一个101状态码,确认转换协议。完成握手后便可以使用websocket协议进行通信。

Client(request)

  1. GET /chat HTTP/1.1
  2. Host: server.example.com
  3. Upgrade: websocket
  4. Connection: Upgrade
  5. Sec-WebSocket-Key: AQIDBAUGBwgJCgsMDQ4PEC==
  6. Origin: http://example.com
  7. Sec-WebSocket-protocol: chat, superchat
  8. Sec-WebSocket-Version: 13

Sec-WebSocket-Key其值采用base64编码的随机16字节长的字符序列,服务器端根据该域来判断client确实是websocket请求而不是冒充的,如http
Sec-WebSocket-protocol使用的子协议
Sec-WebSocket-Version该值必须是13

Server(response)

  1. HTTP/1.1 101 switching Protocols
  2. Upgrade: websocket
  3. Connection: Upgrade
  4. Sec-WebSocket-Accept: dGhlIHNhbXBsZSBub25jZQ==
  5. Sec-WebSocket-Protocol: chat

Sec-WebSocket-Accept值是由client请求首部中的Sec-WebSocket-Key做SHA-1 hash计算,然后再把得到的结果通过base64加密而来

连接建立后,通信的url格式如下:
ws://example.com/
wss://example.com/

参考资料

    1. TCP的三次握手(建立连接)和四次挥手(关闭连接)
    2. 服务器TIME_WAIT和CLOSE_WAIT详解和解决办法

TCP连接建立与释放的更多相关文章

  1. 运输层协议:TCP连接建立与释放

    TCP的特点 面向连接:TCP是面向连接的运输层协议,通过TCP发送数据需要先建立连接,通信结束后需要释放连接 可靠传输:TCP实现了可靠传输,使得数据能够无丢失.无差错.不重复地到达接收端 面向字节 ...

  2. 计算机网络传输层之TCP协议(tcp协议特点、tcp报文段首部格式、tcp连接建立---三次握手、tcp连接释放---四次握手)

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105516090 学习课程:<2019王道考研计算机网络> 学习目的 ...

  3. TCP传输连接建立与释放详解

    一直以来有许多读者朋友对TCP的传输连接建立和释放过程不是很理解,而这又是几乎网络认证中必考的知识点,包括软考.CCNA\CCNP.H3CNA\H3CNE等,为此再把笔者年度巨作,广受好评的——< ...

  4. 网络协议抓包分析——TCP传输控制协议(连接建立、释放)

    前言 TCP协议为数据提供可靠的端到端的传输,处理数据的顺序和错误恢复,保证数据能够到达其应到达的地方.TCP协议是面向连接的,在两台主机使用TCP协议进行通信之前,会先建立一个TCP连接(三次握手) ...

  5. TCP协议-连接建立和释放

    三次握手: (1)客户端向服务器端TCP请求连接,向服务器端发送控制位SYN=1,序号seq=x的请求报文.(x是随机产生的,且不能为0) (2)服务器端接收到请求报文后,若同意建立连接,则向客户端发 ...

  6. TCP 连接建立和断开,以及状态转换

    1. TCP报文结构 TCP是一种可靠.面向连接.全双工的传输层协议,其报文格式如下所示:      源端口.目的端口:16位长.标识出远端和本地的端口号.     顺序号:32位长.表明了发送的数据 ...

  7. TCP连接与释放

    TCP连接的建立 三次握手 TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态. TCP客户进程也是先创建传输控制块TCB,然后向服务器 ...

  8. TCP连接建立与关闭

    http://hi.baidu.com/psorqkxcsfbbghd/item/70f3bd91943b9248f14215cd TCP连接建立与关闭 TCP 是一个面向连接的协议,无论哪一方向另一 ...

  9. TCP连接建立和终止小结

    TCP连接建立(三次握手) 如图: 请求端发送一个SYN到服务器的相应端口,以及初始序号ISN 服务器发送包含服务器的初始序号的SYN作为应答,同时确认序号设置为客户的ISN+1 客户将确认序号设置为 ...

随机推荐

  1. JAVA-SpringMVC基于注解模式第一个应用

    项目文件结构 1. web.xml配置文件 <?xml version="1.0" encoding="UTF-8"?> <web-app x ...

  2. 如何将.NET 4.0写的Windows service和Web API部署到docker上面

    Web API. 看这篇文章: https://docs.microsoft.com/en-us/aspnet/mvc/overview/deployment/docker-aspnetmvc Win ...

  3. (转)Xen Server删除Local Storage

    1. First, you have to determine the Storage-Repository-UUID: xe sr-list -> write down / take note ...

  4. C++ REST SDK i

    Welcome! The C++ REST SDK is a Microsoft project for cloud-based client-server communication in nati ...

  5. RocketMQ【未完成】

    RocketMQ 是一款快速地.可靠地.分布式.容易使用的消息中间件,由 alibaba 开发,其前身是 metaq,metaq 的第一个版本是可以看成是linkedin的kafka(scala)的j ...

  6. linux install nodejs

    下载/安装python yum install -y bzip2* #nodejs 0.8.5需要,请安装python前,先安装此模块.   wget http://www.python.org/ft ...

  7. 【视频教学】如何利用高德地图IOS SDK进行开发?

    Step1:使用IOS SDK可以做什么高德地图 iOS SDK 是一套基于 iOS 5.1.1 及以上版本的地图应用程序开发接口.通过该接口,用户可使用高德地图数据和服务轻松构建功能丰富.交互性强的 ...

  8. JAVA中使用Apache HttpComponents Client的进行GET/POST请求使用案例

    一.简述需求 平时我们需要在JAVA中进行GET.POST.PUT.DELETE等请求时,使用第三方jar包会比较简单.常用的工具包有: 1.https://github.com/kevinsawic ...

  9. unable to find the sources of your current Linux kernel.

    运行 sh ./VBoxLinuxAdditions.run 时FAILED,查看日志: /tmp/vbox.0/Makefile.include.header:97: *** Error: unab ...

  10. tpcc-mysql 系列一:安装使用

    1:安装epel包: rpm -Uvh http://dl.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm 2: yum i ...