TCP/IP协议头部结构与解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27173485/article/details/76976810

参考  http://blog.sina.com.cn/s/blog_634d74310102vmfn.html


IP协议 


  IP协议(Internet Protocol)是网络层协议,用在因特网上,TCP,UDP,ICMP,IGMP数据都是按照IP数据格式发送得。IP协议提供的是不可靠无连接得服务。IP数据包由一个头部和一个正文部分构成。正文主要是传输的数据,我们主要来理解头部数据,可以从其理解到IP协议。  

IP数据包头部格式(RFC791) 
 

  Example Internet Datagram Header 

  上面的就是IP数据的头部格式,这里大概地介绍一下。  

  IP头部由20字节的固定长度和一个可选任意长度部分构成,以大段点机次序传送,从左到 右。  

TCP协议格式

  TCP协议(TRANSMISSION CONTROL PROTOCOL)是传输层协议,为应用层提供服务,和UDP不同的是,TCP协议提供的可靠的面向连接的服务。在RFC793中是基本的TCP描述。关于TCP协议的头部格式内容的说明:  

TCP Header FORMat  
 
 
  TCP Header FORMat  

  跟IP头部差不多,基本的长度也是20字节。TCP数据包是包含在一个IP数据报文中的。


UDO数据段格式

  UDP是一种不可靠的、无连接的数据报服务。源主机在传送数据前不需要和目标主机建立连接。数据被冠以源、目标端口号等UDP报头字段后直接发往目的主机。这时,每个数据段的可靠性依靠上层协议来保证。在传送数据较少、较小的情况下,UDP比TCP更加高效。

  

  如图2-6所示,是UDP头部结构(RFC 793、1323):

    

   图2-6  UDP数据段格式

  

  ●源、目标端口号字段:占16比特。作用与TCP数据段中的端口号字段相同,用来标识源端和目标端的应用进程。

  

  ●长度字段:占16比特。标明UDP头部和UDP数据的总长度字节。

  

  ●校验和字段:占16比特。用来对UDP头部和UDP数据进行校验。和TCP不同的是,对UDP来说,此字段是可选项,而TCP数据段中的校验和字段是必须有的。




解析:
private IP4Header(ByteBuffer buffer) throws UnknownHostException
{
    byte versionAndIHL = buffer.get();
    //Version IP 协议的版本号,4个bit。目前只支持版本4和版本6。
    // 由于 IPv4 的 header 格式和 IPv6 的不一样,所以 Version 字段放在 header 的最前面
    this.version = (byte) (versionAndIHL >> 4);//右移4个字节  (取前一字节)
    //Header Length (IHL) IP header 的长度,包括 IP Options 的长度,但不包括所负载的数据长度。
    // 这个字段占4个bit,每一个bit表示4个字节(units of 32 bits),这个字段最大值是0xFFFF (15),
    // 所以 IPv4 Header 最长占60个字节,去掉IP Header 中固定的20个字节的长度,
    // 剩下可有40个字节的长度留给 IP Options
    this.IHL = (byte) (versionAndIHL & 0x0F);//两个操作数中位都为1,结果才为1,否则结果为0  1111  (截取后一int)
    this.headerLength = this.IHL << 2;//左移两个字节 (乘以4)

    //Type of Service (TOS)
    //服务类型,占8个bit。这个字段标明这个数据报属于何种类型的应用,需要网络层上的路由器怎么处理。
    //它关系到优先级和拥塞控制等,比如是要尽量低延迟的还是高吞吐型的。这个字段又分几个子字段,
    // 而且其间的组合和含义又被 IETF 改变过。
    this.typeOfService = BitUtils.getUnsignedByte(buffer.get());
    //整个IP数据报的长度,以字节为单位,包括 IP Header 的长度和所负载的数据的长度,占16个bit,两个字节。
    // 那一般情况下实际的所负载的数据的长度就是这个字段的值减去4倍的Header Length的值。
    // 当IP数据报的总长度小于链路层所规定的最小长度时,
    // 链路层协议就会自动填充数据报的长度(但不会改变Total Length这个字段),
    // 所以通过这个字段,上层协议就可以知道这个IP数据报中实际有效的数据量了。
    // IP数据报所负载的数据长度最小为0,最大为64K 字节。
    this.totalLength = BitUtils.getUnsignedShort(buffer.getShort());
    //四个字节 Identification, DF (Don't Fragment), MF (More Fragments), Fragment Offset 这几个字段都是在 IP 分片中会用到。
    this.identificationAndFlagsAndFragmentOffset = buffer.getInt();
    //一个字节 Time To Live (TTL)
    //IP数据报在网络上存活的时间,其实是数据报在网络上路由器间转发的次数。
    // 每个路由器在接受到一个数据报时都会把它的TTL值减1,当TTL值为0时就会 被路由器丢弃,
    // 并会向IP数据报中 source IP 发送一个 ICMP 的错误信息。TTL占8个bit,最大跳数为255。
    this.TTL = BitUtils.getUnsignedByte(buffer.get());
    //Protocol传输层协议字段,这个字段表明这个IP数据报是使用 L4 中哪一种协议的,
    // 常见的值有 IPPROTO_ICMP = 1,IPPROTO_TCP = 6, IPPROTO_UDP = 17 等。
    this.protocolNum = BitUtils.getUnsignedByte(buffer.get());
    this.protocol = TransportProtocol.numberToEnum(protocolNum);
    //Header Checksum IP数据报头的校验码,不包含其所负载的数据的校验,那是 L4 的事。
    this.headerChecksum = BitUtils.getUnsignedShort(buffer.getShort());
    //Source Address, Destination Address IP数据报的发送和接受IP地址
    byte[] addressBytes = new byte[4];
    buffer.get(addressBytes, 0, 4);
    this.sourceAddress = InetAddress.getByAddress(addressBytes);

    buffer.get(addressBytes, 0, 4);
    this.destinationAddress = InetAddress.getByAddress(addressBytes);
    //八字节  Options
    //IP数据报选项字段,长度介于0到40字节之间。
    //this.optionsAndPadding = buffer.getInt();
}
private TCPHeader(ByteBuffer buffer)
{
    //两字节段,表示本地端口号  进制为16
    this.sourcePort = BitUtils.getUnsignedShort(buffer.getShort());
    //两字节段,表示目标端口号 进制为16
    this.destinationPort = BitUtils.getUnsignedShort(buffer.getShort());
    //接下来的四个字节“是顺序号(Sequence Number)简写为SEQ
    this.sequenceNumber = BitUtils.getUnsignedInt(buffer.getInt());
    //接下来四个字节是确认号(Acknowledgment Number),简写为ACKNUM
    this.acknowledgementNumber = BitUtils.getUnsignedInt(buffer.getInt());
    this.dataOffsetAndReserved = buffer.get();
    //第一个4bit ,是TCP头长,十进制*4,2bit 没有用上
    this.headerLength = (this.dataOffsetAndReserved & 0xF0) >> 2;
    //前面2bit 没有用上  后面6bit
    //URG:(Urgent Pointer field significant)紧急指针。用到的时候值为1,用来处理避免TCP数据流中断 
    //ACK:(Acknowledgment fieldsignificant)置1时表示确认号(AcknowledgmentNumber)为合法,为0的时候表示数据段不包含确认信息,确认号被忽略。 
    //PSH:(Push Function),PUSH标志的数据,置1时请求的数据段在接收方得到后就可直接送到应用程序,而不必等到缓冲区满时才传送。 
    //RST:(Reset the connection)用于复位因某种原因引起出现的错误连接,也用来拒绝非法数据和请求。如果接收到RST位时候,通常发生了某些错误。 
    //SYN:(Synchronize sequence numbers)用来建立连接,在连接请求中,SYN=1,ACK=0,连接响应时,SYN=1,ACK=1。即,SYN和ACK来区分Connection Request和Connection Accepted。 
    //FIN:(No more data from sender)用来释放连接,表明发送方已经没有数据发送了。
    this.flags = buffer.get();
    //窗口大小
    this.window = BitUtils.getUnsignedShort(buffer.getShort());
    //校验和
    this.checksum = BitUtils.getUnsignedShort(buffer.getShort());
    //紧急指针
    this.urgentPointer = BitUtils.getUnsignedShort(buffer.getShort());
    //选项和数据
    int optionsLength = this.headerLength - TCP_HEADER_SIZE;
    if (optionsLength > 0)
    {
        optionsAndPadding = new byte[optionsLength];
        buffer.get(optionsAndPadding, 0, optionsLength);
    }
}
private UDPHeader(ByteBuffer buffer)
        {
            //源端口号  16比特
            this.sourcePort = BitUtils.getUnsignedShort(buffer.getShort());
            //目标端口号 16比特
            this.destinationPort = BitUtils.getUnsignedShort(buffer.getShort());
            //标明UDP头部和UDP数据的总长度字节
            this.length = BitUtils.getUnsignedShort(buffer.getShort());
            //校验和字段:占16比特。用来对UDP头部和UDP数据进行校验。
            // 和TCP不同的是,对UDP来说,此字段是可选项,而TCP数据段中的校验和字段是必须有的。
            this.checksum = BitUtils.getUnsignedShort(buffer.getShort());
        }


private static class BitUtils
{
    private static short getUnsignedByte(byte value)
    {
        return (short)(value & 0xFF);
    }

    private static int getUnsignedShort(short value)
    {
        return value & 0xFFFF;
    }

    private static long getUnsignedInt(int value)
    {
        return value & 0xFFFFFFFFL;
    }
}



 
 
 
 
 
 
 
 

这里只讲解了TCP/IP协议的一点点东西,主要是头部数据的格式。(T002)

===============================================================================

 

附加图片,直观具体,帮助理解

 

 

 

 

 


猜你喜欢

转载自blog.csdn.net/qq_27173485/article/details/76976810