zoukankan      html  css  js  c++  java
  • TCP 协议

    ==

    已经了解了以太网和IP了,下面我们进入传输层,开始讲解TCP协议。

    ==

    仍然先把TCP报文段的格式放在这里,然后我们看图说话:

    TCP报文段也分为首部和数据两部分,首部默认情况下一般是20字节长度,但在一些需求情况下,会使用“可选字段”,这时,首部长度会有所增加。                   

    下面,我们仍然延续讲解IP协议的思路,针对不同的域, 解:                            

    【源端口】- 16bit   

    来源处的端口号;

    【目的端口】- 16bit

    目的处的端口号;

    【序号】- 32bit

    每一个TCP报文段都会有一个序号,序号字段的值其实是本报文段所发送的数据的第一个字节的序号。这是因为TCP是面向连接的可靠服务,其每一个字节都会对应一个序号,通过序号来确保服务的可靠性和有序性。

    【确认号】- 32bit

    确认号,是期望收到对方的下一个报文段的数据的第一个字节的序号。(这句话有些拗口,但是在后面我们讲解三次握手和四次挥手时,大家会更深刻的理解这句话的含义)

    【数据偏移】- 4bit

    其实它本质上就是“首部长度”,因为“数据偏移”是指TCP报文段的数据部分的起始处距离TCP报文段的起始处的距离。(仍然很拗口,但相信你能明白)。

    数据偏移总共占4bit,因此最大能表示的数值为15。而数据偏移的单位是“4字节”,此处的设计和IP数据报的设计是完全相同的,所以说TCP报文段首部的长度最长为15×4=60字节,且首部长度必须为4字节的整数倍

    【保留字段】- 6bit

    6bit在标准中是保留字段,我猜测,有两个目的,第一个是预留除URG/ACK/PSH/RST/SYN/FIN/之外的冗余功能位;第二个是为了对其字节位。

    【紧急字段URG】- 1bit

    此字段告诉系统此报文段中有紧急数据,应尽快传送。当URG=1时,

    【确认字段ACK】- 1bit

    当ACK=1时,表示确认,且确认号有效;当ACK=0时,确认号字段无效

    【推送字段PSH】- 1bit

    当PSH=1时,则报文段会被尽快地交付给目的方,不会对这样的报文段使用缓存策略。

    【复位字段RST】- 1bit

    当RST为1时,表明TCP连接中出现了严重的差错,必须释放连接,然后再重新建立连接。

    【同步字段SYN】- 1bit

    当SYN=1时,表示发起一个连接请求。

    终止字段FIN】- 1bit (finish)

    用来释放连接。当FIN=1时,表明此报文段的发送端的数据已发送完成,并要求释放连接。

    【窗口字段】- 16bit

    此字段用来控制对方发送的数据量,单位为字节。

    一般TCP连接的其中一端会根据自身的缓存空间大小来确定自己的接收窗口大小,然后告知另一端以确定另一端的发送窗口大小。

    【校验和字段】- 16bit

    这个校验和是针对首部和数据两部分的。

    【紧急指针字段】- 16bit

    紧急指针指出在本报文段中的紧急数据的最后一个字节的序号。

    PS:对于后面的选项字段,后续会安排单独讲解:)

    --------另一篇:

    TCP之所以能为数据通讯提供可靠的传输,主要在于TCP数据包头部功能非常多。

    那么,我们先来看看TCP头部格式(RFC 793、1323定义了TCP头部):

    TCP头部格式中的内容解析如下:(文末还有Wireshark对TCP抓包分析图)

    (根据上图,按从上往下,从左往右的顺序)

    • Source Port:16bit源端口,数据发起者的端口号;
    • Destination Port:16bit目的端口,数据接收方的端口号;
    • Sequence Number:32bit的序列号,由发送方使用;
    • Acknowledgment Number:32bit的确认号,接收数据方返回给发送方的通知,会在确认号的基础上加1;
    • Data Length:4bit头部长度,TCP头部长度一般为20字节,若TCP头部的Options选项启用,则会增加;
    • 下面一部分为TCP的功能bit:
      1. ReservedReservedNonceCWRECN-Echo:共6bit的保留功能,留待以后开发新技术时使用;
      2. URG:1bit紧急指针位,取值1代表这个数据是紧急数据需加速传递,取值0代表这是普通数据;
      3. ACK:1bit确认位,取值1代表这是一个确认的TCP包,取值0则不是确认包;
      4. PSH:1bit紧急位,取值1代表要求发送方马上发送该分段,而接收方尽快的将报文交给应用层,不做队列处理。取值0阿迪表这是普通数据;
      5. RST:1bit重置位,当tcp收到一个不属于该主机的任何一个连接的数据,则向对方发一个复位包,此时该位取值为1,若取值为0代表这个数据包是传给自己的;
      6. SYN:1bit请求位,取值1代表这是一个TCP三次握手的建立连接的包,取值为0就代表是其他包;
    • FIN:1bit完成位,取值1代表这是一个TCP断开连接的包,取值为0就代表是其他包;
    • Window Size:16bit窗口大小,表示准备收到的每个TCP数据的大小;
    • Checksum:16bit的TCP头部校验,计算TCP头部,从而证明数据的有效性;
    • Urgent Pointer:16bit紧急数据点,当功能bit中的URG取值为1时有效;(参考:TCP中URG和PSH以及Urgent Point的作用及区别)
    • Options:TCP的头部最小20个字节。如果这里有设置其他参数,会导致头部增大;
    • Padding:当TCP头部小于20字节时会出现,不定长的空白填充字段,填充内容都是0,但是填充长度一定会是32的倍数;
    • Data:被TCP封装进去的数据,包含应用层协议头部和用户发出的数据。

    Wireshark对TCP抓包分析图

    大家也可以对照着下面这张Wireshark对TCP抓包分析图,看看一个真正基于TCP数据包中,TCP头部格式是怎样的。

    下图为一个telnet数据包的格式,telnet用的传输层协议就是TCP,下图中被红线框中的就是TCP头部:

    http://roclinux.cn/?p=2523

    http://www.ctowhy.com/125.html

    http://www.cnblogs.com/ulihj/archive/2011/01/06/1927613.html

    在TCP层,有个FLAGS字段,这个字段有以下几个标识:SYN, FIN, ACK, PSH, RST, URG.

    其中,对于我们日常的分析有用的就是前面的五个字段。

    它们的含义是:

    SYN表示建立连接,

    FIN表示关闭连接,

    ACK表示响应,

    PSH表示有 DATA数据传输,

    RST表示连接重置。

    其中,ACK是可能与SYN,FIN等同时使用的,比如SYN和ACK可能同时为1,它表示的就是建立连接之后的响应,

    如果只是单个的一个SYN,它表示的只是建立连接。

    TCP的几次握手就是通过这样的ACK表现出来的。

    但SYN与FIN是不会同时为1的,因为前者表示的是建立连接,而后者表示的是断开连接。

    RST一般是在FIN之后才会出现为1的情况,表示的是连接重置。

    一般地,当出现FIN包或RST包时,我们便认为客户端与服务器端断开了连接;而当出现SYN和SYN+ACK包时,我们认为客户端与服务器建立了一个连接。

    PSH为1的情况,一般只出现在 DATA内容不为0的包中,也就是说PSH为1表示的是有真正的TCP数据包内容被传递。

    TCP的连接建立和连接关闭,都是通过请求-响应的模式完成的。

    概念补充-TCP三次握手:

    TCP(Transmission Control Protocol)传输控制协议

    TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接:

    位码即tcp标志位,有6种标示:SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急)Sequence number(顺序号码) Acknowledge number(确认号码)

    第一次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机;

    第二次握手:主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321的包;

    第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。

    完成三次握手,主机A与主机B开始传送数据。



    在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
    第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
    第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

    第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。完成三次握手,客户端与服务器开始传送数据.

     -=----------------------------

    三次握手:
    握手过程的第一个段的代码位设置为SYN,序列号为x,表示开始一次握手。接收方收到这个段后,向发送者回发一个段。代码位设置为SYN和ACK,序列号设置为y,确认序列号设置为x+1。发送者在受到这个段后,知道就可以进行TCP数据发送了,于是,它又向接收者发送一个ACK段,表示,双方的连接已经建立。
    Client --> 置SYN标志 序列号 = J,确认号 = 0 ----> Server
    Client <-- 置SYN标志 置ACK标志 序列号 = K, 确认号 = J + 1 <-- Server
    Clinet --> 置ACK标志 序列号 = J + 1,确认号 = K + 1 --> Server
    a 发起方 b接受方
    a发送一个SYN包给b,b回一个[SYN,ACK]给b,a再回一个ACK包给b;

    数据交换:
    a ----》b
    a 发送数据完毕,(PSH,ACK) aseq = x,ack=y,datalen = z
    b 接受到以后发送(ACK)  bseq = aack, back = aseq + alen, datalen=blen
    b 发送数据完毕  (PSH,ACK)bseq = bseq + blen,back = back,datalen = blen
    a  确认接受     (ACK)   aseq = back ,aack = bseq + blen
    注:PSH标志指示接收端应尽快将数据提交给应用层。从我协议分析的经历来看,在数据传输阶段,几乎所有数据包的发送都置了PSH位;而ACK标志位在数据传输阶段也是一直是置位的

    在数据传输阶段,按照常理应用层数据的传输是这样的:(我们假定建立连接阶段Client端最后的确认包中序列号 = 55555, 确认号 = 22222)
    Client --> 置PSH标志,置ACK标志 序列号 = 55555, 确认号 = 22222,数据包长度 = 11 ---> Server 
    Client <-- 置ACK标志,序列号 = 22222, 确认号 = 55566 (=55555 + 11),数据包长度 = 0 <--- Server
    Client <-- 置PSH标志,置ACK标志 序列号 = 22223, 确认号 = 55566,数据包长度 = 22 <--- Server 
    Client --> 置ACK标志,序列号 = 55566, 确认号 = 22244(=22222+22),数据包长度 = 0 ---> Server
    /////////////////////////////////////////////////////////////////////////////////////////

  • 相关阅读:
    伪句柄
    WM_NCACTIVE
    怎么让模态对话框最小化时,主窗口也最小化
    CMap和CArray中ARG_
    看着嫦娥2号上去,心里激动不已
    Qt中使两个部件同步,这里为spin和slider
    memcpy 和strcpy的区别
    如何在linux内核中读写文件
    Could not find *****/adb.exe!的解决方法(android sdk太新了?**#¥)
    加入了HTML特点的Qt,出来的效果不错哟
  • 原文地址:https://www.cnblogs.com/youxin/p/3565437.html
Copyright © 2011-2022 走看看