一、首先了解TCP报文格式

其中必须了解的字段有:

1、源端口与目的端口:16位,标识出发送端与接收端的端口号。

2、序号:32位,也叫顺序号、seg序号,本报文段所发送的数据的第一个字节的序号,用来标记数据报顺序。

3、确认号:32位,ack序号,用来标记期待收到对方下一个报文段的第一个数据字节的序号,确认信号ack=发送过来的seg+1,收发两端配对。

4、标志位:共有6个。

ACK起应答作用,占1位;仅当ACK=1时,确认号字段才有效,ACK=0时,确认号无效。

SYN起同步作用;当SYN=1,ACK=0时表示:这是一个连接请求报文段。若同意连接,则在响应报文段中使得SYN=1,ACK=1。因此,SYN=1表示这是一个连接请求,或连接接受报文。

FIN用来释放一个连接;FIN=1表示:此报文段的发送方的数据已经发送完毕,并要求释放运输连接。

PSH表示接收方应将报文交给应用层,
RST表示连接重置,
URG表示紧急指针,不常用。

二、“三次握手”

概念:所谓“三次握手”就是TCP连接建立的过程,即需要客户端与服务端总共发送三个包(所以着重记忆这三个包就可以了)以确认连接的建立。

意义:通过“三次握手”保证了客户端与服务器建立的是双工连接,而可靠性是更多是通过重发机制实现的。

其它:在Socket编程中,这一过程由客户端执行connect来触发。

流程图如下:

(注:如下出现的ack与ACK标志不能混淆,前者是确认序号,后者是TCP状态标识位应答标识,切记!)

1、第一次握手:客户端发送SYN包(SYN=1,令ack=0,随机产生一个值给seg,seg=X)给服务器端请求连接,客户端进入SYN_SENT,等待服务器端确认。

2、第二次握手:服务器端接收SYN包,由SYN=1知道客户端请求连接,服务器端发送SYN+ACK包(SYN=ACK=1,ack=X+1,随机产生一个值给seg,seg=Y)给客户端确认连接请求,服务器端进入SYN_RCVD状态。

3、第三次握手:客户端收到服务器的SYN+ACK包后,检查ack是否为X+1,ACK标志是否为1,如果正确,发送ACK包(ACK标志置为1,令ack=Y+1),并将该数据包发送给服务器端;服务器端检查ack是否为Y+1,ACK标志是否为1,如果正确则建立连接,客户端与服务器端进入ESTABLISHED状态,完成三次握手,可以开始传输数据了!

三、“四次挥手”

概念:所谓“四次挥手”就是关闭TCP连接的过程,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认双方连接的断开。

意义:同样是保证TCP连接的全双工连接。

其它:在socket编程中,这一过程由客户端或服务端任一方执行close来触发。

流程图如下:

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN包来终止这个方向的连接。收到一个 FIN包只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

1、第一次挥手:客户端发送一个FIN包(FIN=1,随机产生一个值给seg,seg=u)给服务器端,用来关闭客服端到服务器端的数据传输,客户端进入FIN_WAIT_1状态。

2、第二次挥手:服务器端收到FIN包后,发送一个ACK包(ACK=1,ack=u+1,在随机产生一个值给seg,seg=v)给客户端,客户端进入CLOSE_WAIT状态。

3、第三次挥手:服务器端发送一个FIN包(FIN=1,ACK=1,ack=u+1,在随机产生一个值给seg,seg=w)给客户端,用来关闭服务器端到客户端的数据传输,服务器端进入LAST_ACK状态。

4、第四次挥手:客户端接收FIN包,然后进入TIME_WAIT状态,接着发送一个ACK包(ACK=1,seq=u+1,ack=w+1)给服务器端,服务器端确认序号,进入CLOSED状态,完成四次挥手。

上述挥手过程是一方主动,另一方被动,然而有一定可能性是,双方同时主动申请关闭连接,这种情况流程图如下:

同时挥手:

四、其他问题(转载自星宇蓝海的博客http://www.cnblogs.com/cy568searchx/p/3711670.html)

1.为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
 
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的.
 
2.为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
 
这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。

3、状态说明

CLOSED: 这个没什么好说的了,表示初始状态。
 
LISTEN: 这个也是非常容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,可以接受连接了。
 
SYN_RCVD: 这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本 上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态 时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。
 
SYN_SENT: 这个状态与SYN_RCVD遥想呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。
 
ESTABLISHED:这个容易理解了,表示连接已经建立了。
 
FIN_WAIT_1: 这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别 是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即 进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马 上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。

FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。

TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。

CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什 么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报 文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。

CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对 方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。

LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。

最新文章

  1. (原)3.1 Zookeeper应用 - Master选举
  2. js 事件冒泡
  3. Lambda GroupBy Sum
  4. (翻译) TFS源代码控制的未来 (TFSVC vs. Git)
  5. 我心目中的Asp.net核心对象
  6. spring常用jar包总结(转载)
  7. MapReduce之Writable相关类
  8. Navigation Bar上的返回按钮文本颜色,箭头颜色以及导航栏按钮的颜色
  9. Unity3D 之射线检测
  10. 上传插件webupload之调用拍照兼容问题
  11. Java io 入门
  12. 使用rvm安装与切换Ruby
  13. Mysql 的远程设置 和链接方式
  14. python连接mysql-PyMySql模块
  15. Java SE之String,字符串和子字符串的存储与区别
  16. Python3 tkinter基础 Entry validate validatecommand 失去焦点时,检查输入内容
  17. 一、J2EE
  18. 活字格Web应用平台学习笔记 7 - 导出 Excel
  19. SQL Server复制故障(1)
  20. Java Eclipse编译后产生的字节码文件,用DOS命令符怎么打开

热门文章

  1. phpcms V9二级目录下分页路径不正确问题的彻底解决方法
  2. Python--csv文件处理
  3. hibernate的注解属性mappedBy详解【实际项目】
  4. 《DSP using MATLAB》示例Example7.19
  5. vue 相邻自定义组件渲染错误正确的打开方式
  6. OpenSSH 使用技巧
  7. ①HttpURLConnection通过报文提交
  8. Angular2使用boostrap和ng-bootstrap总结
  9. List<Map> 排序
  10. FPGA应用及ARM-FPGA架构举例