TCP(Transmission Control Protocol) 传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议。

  TCP是一种面向连接(连接导向)的、可靠的基于字节流的传输层通信协议。TCP将用户数据打包成报文段,它发送后启动一个定时器,另一端收到的数据进行确认、对失序的数据重新排序、丢弃重复数据。

  TCP把连接作为最基本的对象,每一条TCP连接都有两个端点,这种断点我们叫作套接字(socket),将端口号拼接到IP地址即构成了套接字,例如,若IP地址为192.3.4.16 而端口号为80,那么得到的套接字为192.3.4.16:80。

  

TCP的特点有:

  • TCP是面向连接的运输层协议;
  • 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的;
  • TCP提供可靠交付的服务;
  • TCP提供全双工通信。数据在两个方向上独立的进行传输。因此,连接的每一端必须保持每个方向上的传输数据序号;
  • 面向字节流。【面向字节流的含义:虽然应用程序和TCP交互是一次一个数据块,但TCP把应用程序交下来的数据仅仅是一连串的无结构的字节流。】

TCP报文格式图:

TCP报文首部:

1、源端口和目的端口,各占2个字节,分别写入源端口和目的端口;
2、序号,seq序号,sequence number,占4个字节,TCP连接中传送的字节流中的每个字节都按顺序编号,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。例如,一段报文的序号字段值是 301 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从401开始;
3、确认号,ack序号,acknowledge number,占4个字节,是期望收到对方下一个报文的第一个数据字节的序号。例如,B收到了A发送过来的报文,其序列号字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701;
4、数据偏移,占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远;
5、保留,占6位,保留今后使用,但目前应都位0;
6、标志位:(共6个,即URG、ACK、PSH、RST、SYN、FIN等)

      • 紧急URG,当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据;
      • 确认ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;
      • 推送PSH,当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应,这时候就将PSH=1;
      • 复位RST,当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接;
      • 同步SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1;
      • 终止FIN,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放;

7、窗口,占2字节,指的是通知接收方,发送本报文你需要有多大的空间来接受;
8、检验和,占2字节,校验首部和数据这两部分;
9、紧急指针,占2字节,指出本报文段中的紧急数据的字节数;
10、选项,长度可变,定义一些其他的可选的参数。

需要注意的是:
  (a)不要将确认序号ack与标志位中的ACK搞混了。
  (b)确认方的确认号码等于发起方的顺序号码加上数字1:ack=seq+1,两端配对。

TCP在传输之前会进行三次沟通,一般称为“三次握手”(Three-Way Handshake),传完数据断开的时候要进行四次沟通,一般称为“四次挥手”。

“三次握手”过程讲解:

  首先,TCP服务器 B 进程先创建传输控制块TCB,时刻准备接受客户进程 A 的连接请求,此时服务器 B 就进入了LISTEN(监听)状态。

  然后【第一次握手】:TCP客户进程 A 也是先创建传输控制块TCB,然后向服务器 B 发出连接请求报文,这时报文首部中的同部位SYN=1,同时选择一个初始序列号 seq=x ,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。

  接着【第二次握手】:TCP服务器 B 收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1(因为已经收到了序列号为x的数据包,准备接收序列号为x+1的包,所以ack=x+1),同时也要为自己初始化一个序列号 seq=y(B告诉A自己的初始序列号)。此时,TCP服务器 B 进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。

  再然后【第三次握手】:TCP客户进程 A 收到确认后,还要向服务器 B 给出确认。确认报文的ACK=1,ack=y+1(ack=y+1是表示A正准备接收B序列号为y+1的数据包),自己的序列号seq=x+1。此时,TCP连接建立,客户端 A 进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。

  最后,当服务器 B 收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。

为什么A在第三次握手中还要发送一次确认呢?

  这主要是为了防止已失效的连接请求报文段突然又传送到了B,B确认后一直长时间等待A发送请求而浪费B的资源。

所谓“已失效的连接请求报文段”是这样产生的:

  正常情况是:A发出连接请求,但因连接请求报文丢失而未收到确认。于是A再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接。A共发送了两个连接请求报文段,其中第一个丢失,第二个到达了B。没有“已失效的连接请求报文段”。

  现假定出现一种异常情况,即A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,以致延误到连接释放以后的某个时间才到达B。本来这是一个早已失效的报文段,但B收到此失效的连接请求报文段后,就误认为是A发出一次新的连接请求;于是B就向A发出确认报文段,同意建立连接。那么,由于现在A并没有发出建立连接的请求,因此不会理睬B的确认,也不会向B发送数据。但B却以为新的运输连接已经建立了,并一直等待A发来数据。这样的话,B的许多资源就这样白白浪费了。

  采用三次握手的办法可以防止上述现象的发生。例如在刚才的情况下,A不向B的确认发出确认,B就由于收不到确认,就认为A并没有要求建立连接。

“四次挥手”过程讲解:

  所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发。

一、如果是一方主动关闭,另一方被动关闭,那么整个流程如下图所示:(下图以客户端主动发起关闭请求为例)

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

  上图描述的即是如此。挥手过程如下:

(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。

(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。

(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。

(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。

二、实际中还会出现同时发起主动关闭的情况,具体流程如下图:

为什么建立连接是三次握手,而关闭连接却是四次挥手呢?

  这是因为:在建立连接时,服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,己方ACK和FIN一般都是分开发送给对方:当收到对方的FIN报文时,仅仅表示对方不再发送数据了,但是对方还能接收己方发送过去的数据;己方如果尚未把全部数据都发送给对方,并且己方如果不立即close,还可以继续发送一些数据给对方,发送完毕后才发送FIN报文给对方来表示同意现在关闭连接。

为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
  这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。

TCP简介的更多相关文章

  1. TCP简介(一)

    1. TCP如何利用IP达到自己目的 1.1 IP特点 无连接 不可靠 1.2 TCP将应用程序的传输数据分割成合适的数据块 1.3 定时器 1.4 延迟确认 1.5 检验和 1.6 流量控制 2. ...

  2. 一起学Python:TCP简介

    TCP介绍 TCP协议,传输控制协议(英语:Transmission Control Protocol,缩写为 TCP)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793 ...

  3. 端口TCP——简介

    cmd命令:telnet 如果需要搭建外网可访问的网站,可以顺便勾选HTTP,HTTPS端口:

  4. TCP那些事

    本文是<TCP-IP详解.卷1 协议>的读书笔记 1 TCP简介 TCP提供一种可靠的.面向连接的字节流服务.TCP通过下面的方式来保证服务是可靠的: 应用程序被分隔成TCP认为最适合发送 ...

  5. 九、Socket之TCP编程

    TCP简介 TCP是Transmission Control Protocol(传输控制协议)的简称,是TCP/IP体系中面向连接的运输层协议,在网络中提供全双工的和可靠的服务. TCP最主要的特点: ...

  6. C#网络程序设计(3)网络传输编程之TCP编程

        网络传输编程指基于各种网络协议进行编程,包括TCP编程,UDP编程,P2P编程.本节介绍TCP编程.     (1)TCP简介: TCP是TCP/IP体系中最重要的传输层协议,它提供全双工和可 ...

  7. TCP三次握手与四次分手

    TCP简介 首先来看看OSI的七层模型: 我们需要知道TCP工作在网络OSI的七层模型中的第四层--Transport层,IP在第三层--Network层,ARP在第二层--Data Link层:在第 ...

  8. tcp入门(唐唐的故事)

    1,互联网的实现,分成好几层.每一层都有自己的功能,就像建筑物一样,每一层都靠下一层支持.把互联网分成五层,容易让人理解. 2,对这五层的理解(唐唐讲故事): 实体层:目的就是把计算机连接起来,用电气 ...

  9. 网络传输编程之TCP

    网络传输编程之TCP   网络传输编程指基于各种网络协议进行编程,包括TCP编程,UDP编程,P2P编程.本节介绍TCP编程.     (1)TCP简介: TCP是TCP/IP体系中最重要的传输层协议 ...

随机推荐

  1. 路由跟踪表满,日志报错nf_conntrack: table full, dropping packet.

    “连接跟踪表已满,开始丢包”!相信不少用iptables的同学都会见过这个错误信息吧,这个问题曾经也困扰过我好长一段时间.此问题的解决办法有四种(nf_conntrack 在CentOS 5 / ke ...

  2. python-函数入门(一)

    1.什么是函数: 可重复使用的,用来实现单一,或相关联功能的代码段. 函数分为内置函数和自定义函数,这里先讲自定义函数 2.如何定义函数: #语法 def 函数名(参数1,参数2,参数3,...): ...

  3. LuoGu P2835 刻录光盘

    题目传送门 这个题和消息扩散那个题,一模一样啊 除了数据范围小一点,搜索能过之外,没啥区别 但是我写WA了QwQ不知道为什么 和消息扩散的代码fc/diff了半天也没找出来哪不一样 换了输入就过了反正 ...

  4. Confluence 6 在 Apache 或者系统级别阻止垃圾

    如果一个垃圾发布机器人攻击你的 Confluence 站点,这些程序可能来自于同一个 IP 地址,或者是一个比较小范围的 IP 地址段.希望找到攻击者的 IP 地址,请参考 Apache access ...

  5. web的分页方法

    web分页的三种方式,闲来无事总结一下. 1.使用前端表格插件进行分页 例如用bootstrap的拓展table组件,注意设置其分页属性时设置为"client", 即是 sideP ...

  6. Android “Command” from work summary

    总结一下Android中的命令. 一.adb 与 shell ADB的全称为Android Debug Bridge(调试桥).是一个适用命令行工具,用来与模拟器实例或链接的Android设备进行通信 ...

  7. FromData获取表单数据

    一般想要不刷新页面提交数据时,可以使用ajax提交.如果数据量不大可以自己写json数据用ajax提交到后台服务,但是数据量多且需要动态添加数据时,自己写json格式数据就有点麻烦了,这时候就需要Fo ...

  8. 如何在cmd中安装python第三方模块

    打开 cmd终端 1 输入pip  install   模块名. 2 等待安装完成即可.

  9. python 之面向对象的三大特性

    面向对象的三大特性 继承 继承和组合 继承进阶 封装 封装(有待完善) 多态 多态

  10. 表达式语言 Expression Language

    JSP 2.0最重要的特性之一就是表达式语言 (EL),JSP用户可以用它来访问应用程序数据.由于 受到ECMAScript和XPath表达式语言的启发,EL也设计 成可以轻松地编写免脚本的JSP页面 ...