天天看点

【TCP/IP】TCP

TCP介绍:

       TCP提供一种面向连接的、可靠的字节流服务。面向连接,TCP一定要有三次握手的建立和四次握手的结束。可靠,TCP传输的每一个字节都需要确认。字节流服务,UDP叫数据报服务,应用层不管给UDP多大一个包,UDP就直接在这个基础之上封装UDP头部、IP头部、以太网头部,然后发走,网络上传输的数据和应用层给的数据是一一对应的。TCP是叫数据流,应用层给的数据,大了会把它拆小,小了会把它组装大,然后在网络上发走,网络上传输的数据和应用层给的数据是没有关系的。

       面向连接意味着两个使用TCP的应用(通常时一个客户和一个服务器)在彼此交换数据之前必须先建立一个TCP连接

       在一个TCP连接中,仅有两方进行彼此通信,TCP的连接肯定是点对点的,TCP肯定是不支持组播和广播的,UDP是可以支持的。

       应用数据被分隔成TCP认为最适合发送的数据块。应用层给的数据,大了会把它拆小,小了会把它组装大,反正TCP会以它认为最合适的大小来发送。

       当TCP发送出一个段后,它启动一个定时器,等待目的端的确认收到这个报文段。如果不能即时收到一个确认,将重发这个报文段。

       当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒。为什么要等呢?因为马上给确认的话,有点浪费资源,发一个确认也是有消耗的,会有以太网头部、IP头部、TCP头部这些头部就有几十个字节,还是会浪费带宽的,但是如果等一会有可能这边的主机也有数据要发给另一端,那样就可以把确认同要发过去的数据用一个数据报一起发走,这样效率就会更高。

       TCP校验和校验的是它的首部、伪首部和数据部分

       既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能失序。如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层

       既然IP数据报会发生重复,TCP的接收端必须丢弃重复的数据

       TCP还能够提供流量控制。TCP连接的每一方都有固定大小的缓冲空间,目的主机会告诉源端主机它的窗口大小是4096个字节,如果说源端发送的太快,目的端的缓冲空间有可能就满了,目的主机就会告诉源端主机它的剩余的缓冲区已经为0了,当源端知道为0后就不会再发了,等缓冲区空闲了之后会继续再发。

       TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机导致使较慢主机的缓冲区溢出

TCP的字节流

      两个应用程序通过TCP连接交换8bit字节构成的字节流。TCP不在字节流中插入记录标识符。我们将这称为字节流服务。如果一方的应用程序先传10字节,又传20字节,再传50字节,连接的另一方将无法了解发送方每次发送了多少字节。接收方可以分4次接收这80个字节,每次接收20字节。一端将字节流放到TCP连接上,同样的字节流将出现在TCP连接的另一端。

     另外,TCP对字节流的内容不作任何解释。TCP不知道传输的数据字节是二进制数据,还是ASCII字符、EBCDIC字符或者其它类型数据。对字节流的解释由TCP连接双方的应用层解释。

TCP包首部:

【TCP/IP】TCP

       源端口和目的端口:各占2字节.端口是传输层与应用层的服务接口.传输层的复用和分用功能都要通过端口才能实现,这2个值加上IP首部中的源端IP地址和目的端IP地址唯一确定一个TCP连接

       序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,它表示在这个报文段中的第一个数据字节。如果将字节流看作再两个应用程序间的单向流动,则TCP用序号对每个字节进行计数。数据部分如果有100个字节,seq就会加100,序号是32bit的无符号数,序号达到2的32次方后又从0开始。如果没有数据只有首部还会加吗?有可能会加,如果SYN或者FIN被置1就会加。因为SYN和FIN标志都是有代价的,SYN标志和FIN标志都将消耗一个序号。发送ACK无需任何代价,因为32bit的确认序号字段和ACK标志一样,总是TCP的一部分。因此,我们看到一旦一个链接建立起来,这个字段总是被设置,ACK标志也总是被设置为1。

       确认号:Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,确认序号是上次已成功收到数据字节序号加1。除了三次握手的第一个包SYN包是没有ACK以外,其余全部都有ACK位,也就是说除了第一个包以外,其他的包的确认序号都是有意义的。TCP为应用层提供全双工服务。这意味数据能在两个方向上独立地进行传输。因此,连接的每一端必须保持在每个方向上的传输数据序号。

       首部长度:占4位,(和IP首部长度一样)它指出 TCP 报文段的数据起始处距离 TCP 报文段的起始处有多远.单位是32 位字(以 4 字节为计算单位)

       保留:占 6 位,保留为今后使用,但目前应置为 0。(有些黑客使用这6位上传数据,来逃避检测。但是现在有些东西会专门查这6个位,如果这6个位不是0,就会丢弃掉)

       紧急URG:当 URG=1 时,表明紧急指针字段有效.它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)

       确认ACK:只有当 ACK=1 时确认号字段才有效.当 ACK=0 时,确认号无效。不要将确认序号Ack与标志位中的ACK搞混了。

       PSH(PuSH):接收 TCP 收到 PSH = 1 的报文段,就尽快地交付接收应用进程,而不再等到整个缓存都填满了后再向上交付,一般现在的PSH位应用程序都不会理睬,收到了就受到了,大家都是一样的,不能说携带了PSH位就要优先,因为应用层序也无法识别你这个PSH合不合法(恶意使PSH位置1),收到了也需要排队。

       RST (ReSeT):当 RST=1 时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接

       同步 SYN:同步 SYN = 1 表示这是一个连接请求或连接接受报文

       终止 FIN:用来释放一个连接.FIN=1 表明此报文段的发送端的数据已发送完毕,并要求释放运输连接

       窗口大小:占2个字节,窗口大小就是一个流控的技术,表明了接收方的剩余缓冲空间的大小。TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小是一个16bit字段,因而窗口大小最大为65535字节。但是有窗口扩大因子来允许这个值按比例变化以提供更大的窗口(原理以后介绍,背景:由于现在的超高速网络,窗口大小最大为65535字节已经远远不够使用,因为在超高速网络中,一发送数据,接收端就会告诉发送端窗口为0了,需要等待,一发送就需要等待。这样效率就会很低,因此有了窗口扩大因子)。如果我的窗口大小是4096个字节,不管你发几个包过来,在没得到我的ACK之前,你发的包总的大小最大为4096个字节。这时候我回复ACK时更改窗口大小为0时,发送端就不会发送数据,会等待接收端发送一个ACK,告诉发送端窗口大小闲置了。接受方对发送方的速度进行限制,不能超过接收方的缓存空间。

       检验和:占2个字节,检验和字段检验的范围包括首部和数据这两部分.在计算检验和时,要在 TCP 报文段的前面加上 12 字节的伪首部

       紧急指针:占2个字节,URG须置1,指出在本报文段中紧急数据共有多少个字节(紧急数据放在本报文段数据的最前面)

       选项:长度可变.TCP 最初只规定了一种选项,即最大报文段长度 MSS(MTU-IP首部-TCP首部=1460).MSS 告诉对方 TCP:“我的缓存所能接收的报文段的数据字段的最大长度是 MSS 个字节.” [MSS(Maximum Segment Size)是 TCP 报文段中的数据字段的最大长度.数据字段加上 TCP 首部才等于整个的TCP 报文段]

       TCP报文段中的数据部分是可选的

TCP数据在IP数据报中的封装:

【TCP/IP】TCP

TCP可以表述为一个没有选择确认或否认的滑动窗口协议。我们说TCP缺少选择确认是因为TCP首部中的确认序号表示发方已成功收到字节,但还不包含确认序号所指的字节,无法对数据流中选定的部分进行确认。例如,如果1~1024字节已经成功收到,接收端会发送一个确认号为1025的报文确认,下一报文段中序号从1025~2048字节的报文因为什么原因没有收到,在重发定时器还没到期时,2049~3072字节和后续的包已经到了,而且接收端也收到了。这时候接收端不能告诉发送到我接收到了1~1024和2049~3072的包和后续的包,没有收到1025~2048的包,接收端所能做的就是每接收到一段字节的包后,过几分之一秒发送确认序号为1025的ACK给发送端。当发送端多次收到1025的ACK时,就会发现问题,这时候它可能(什么原因不清楚)会把1025之后的包一起打包成一个大包发送过去。或者等到重发定时器到期时,发送端依次重新发送1025后续的包。没有否认,当接收到接收到1~1024字节的包后,在检查CRC时校验失败把包丢了,这时候接收端不能告诉发送端,已经接收到了1~1024字节的包,因为CRC校验失败丢弃了。接收端只能发送一个ACK为1的包告诉发送端。要求发送端发送从1开始的包。

继续阅读