Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1334677
  • 博文数量: 284
  • 博客积分: 3251
  • 博客等级: 中校
  • 技术积分: 3046
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-26 17:23
文章分类

全部博文(284)

文章存档

2019年(2)

2018年(5)

2015年(19)

2014年(13)

2013年(10)

2012年(235)

分类: LINUX

2012-12-21 16:46:40

    TCP数据被封装在一个IP数据报中,TCP首部在数据报中的位置跟UDP首部一样,紧跟在IP首部后面。为简单起见,我们先看不计任何选项的TCP首部,它总共20字节,下面是其定义:
    struct tcphdr {
        __u16   source;
        __u16   dest;
        __u32   seq;
        __u32   ack_seq;
#if defined(__LITTLE_ENDIAN_BITFIELD)
        __u16   res1:4,
                doff:4,
                fin:1,
                syn:1,
                rst:1,
                psh:1,
                ack:1,
                urg:1,
                ece:1,
                cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
        __u16   doff:4,
                res1:4,
                cwr:1,
                ece:1,
                urg:1,
                ack:1,
                psh:1,
                rst:1,
                syn:1,
                fin:1;
#else #error  "Adjust your defines"
#endif
        __u16   window;
        __u16   check;
        __u16   urg_ptr;
    };
    下面我们依次介绍每个字段的含义。
    source和dst分别表示源和目的端口号,每个TCP段都包含源端口号和目的端口号,用于寻找发送端和接收端的应用进程,这两个值加上IP首部中的源端IP地址和目的端IP地址就可以唯一确定一个TCP连接。
    seq是发送端序列号,用于标识从TCP发送端向接收端发送的数据字节流,也就是说,每发送一个字节,该字段值加1,为了安全起见,它的初始值是一个随机 生成的数,它到达32位最大值后,又从零开始。ack_seq是确认序列号,发送给对端,用于确认希望对端发送的下一个数据报的起始序号,显然,一个 TCP客户端发起连接请求时,ack_seq的值为0。
    doff占4位,表示首部长度,它的单位并非字节,而是32bit,所以,一个不含任何选项的TCP首部,其首部长度是5(5*4=20字节),含有选项时,还要加上选项的长度。res1为保留位,cwr, ece用途暂时不明。
    window是16位滑动窗口的大小,单位为字节,起始于确认序列号字段指明的值,这个值是接收端正期望接收的字节数,其最大值是63353字节。
    check是检验和,覆盖了整个的TCP报文段,这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证。
    urg_ptr是一个紧急指针,是一个正的偏移量,和序列号字段中的值相加表示紧急数据最后一个字节的序列号。
    urg, ack, psh, rst, syn, fin为6个标志位,它们的含义如下:
    urg: 紧急指针有效。
    ack: 确认序号有效。
    psh: 接收方应该尽快将这个报文段交给应用层。
    rst: 重建连接。
    syn: 同步序号,用来发起一个连接。
    fin: 发送端完成发送任务。
    内核源代码在函数mytcp_transmit_skb中建立tcp首部。
阅读(907) | 评论(0) | 转发(1) |
0

上一篇:TCP socket上的connect(1)

下一篇:TCP首部(2)

给主人留下些什么吧!~~