TCP中32位序号详解

首先解释一段截取的网络数据认识一下。(由a_la_lei解释)

1、-> syn(这一步是初始化发送端的ISN。理论上,它的数据字段没有任何值,消耗的是一个虚字节)
TCP: Sequence number = 4071231308
TCP: Acknowledgement number = 0

2、<- ack syn(初始化接收端的ISN,并对收到的包进行确认。因为确认的方式是累计确认,所以尽管第1步传输了一个虚字节,但ACK仍旧是4071231308+1=4071231309)
TCP: Sequence number = 1191340143
TCP: Acknowledgement number = 4071231309

3、-> ack(回应第2步的确认。因为第1步消耗的是一个虚字节,所以理论上Seq应该仍旧是4071231308,但由于协议的具体实现略有不同,这里又在虚字节上加1变成4071231309。仍旧是累计确认。)
TCP: Sequence number = 4071231309
TCP: Acknowledgement number = 1191340144

4、-> ack push 登录信息(载荷包。因为第3步仅是一个确认包,它没有包含任何有效数据,所以这里的Seq仍旧是4071231309。仍旧是对第2步确认)
TCP: Sequence number = 4071231309
TCP: Acknowledgement number = 1191340144

5、<- ack(仅仅是一个确认包。仍旧是根据累计确认原则对第4步确认,ACK等于4071231309+有效载荷=4071231337)
TCP: Sequence number = 1191340144
TCP: Acknowledgement number = 4071231337

6、<- ack push 回应信息(载荷包。因为第5步仅仅是一个确认包,所以这里不消耗任何序号,Seq仍旧是1191340144。ACK仍旧是对第4步的确认)
TCP: Sequence number = 1191340144
TCP: Acknowledgement number = 4071231337

7、-> ack(仅仅是一个确认包。仍旧是根据累计确认原则对第6步确认,ACK等于1191340144+有效载荷=1191340217)
TCP: Sequence number = 4071231337
TCP: Acknowledgement number = 1191340217

8、<- ack push 第二次回应信息(载荷包。因为仍旧有数据要发送,按第7步给予的ACK来设置此包的Seq。此包的Ack仍旧是4071231337)
TCP: Sequence number = 1191340217
TCP: Acknowledgement number = 4071231337

本流程需要知道的几个规则:

规则1、累计确认。接收端对收到的载荷包(数据字段有值的TCP包),回应一个确认包,确认号是所收到包的TCP数据字段最后一个字节+1。
规则2、捎带确认。载荷包必须捎带确认字段。这样可以减少网络流量。
规则3、虚字节。有些数据包(ACK)不携带任何数据,所以不消耗序列号,也就是说仍旧保持不变。

uip中,序号的操作流程

三次握手:第一次        第二次             第三次
seqno:1713796940        2957476497         1713796941
ackno:0                 1713796941         2957476498
      SYN = 1 ACK = 0   SYN = 1 ACK = 1    SYN = 0 ACK = 1
seqno:32位序号,表示在这个报文段中的的第一个数据字节。:我发送的数据段第一个字节的序列号是。
ackno:32位确认序号包含发送确认的一端所期望收到的下一个序号。:我希望下次接收到的数据段第一个字节的序列号。

u8_t snd_nxt[4];    // 下一次发送的起始字节的序列号
u8_t rcv_nxt[4];    // 上一次接收起始字节的序列号

u8_t iss            /TCP初始化序列号
u8_t uip_acc32[4];  /临时变量无意义/
u8_t BUF->seqno[1]...[4];       //TCP里的32位序号
u8_t BUF->ackno[1]...[4];       //TCP里的32位确认序号

void uip_add_rcv_nxt(u16_t n)   // 功能:(u32_t)rcv_nxt = (u32_t)rcv_nxt + n
{}

1.主动链接中的应用:
uip_connect()                   // 主动发起链接函数
{
  conn->snd_nxt[0] = iss[0];    // 用于第一次握手的seqno
  conn->snd_nxt[1] = iss[1];
  conn->snd_nxt[2] = iss[2];
  conn->snd_nxt[3] = iss[3];
}
found:中主动链接部分
if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) {    // 收到了ACK帧,同时有待确认的数据;
    uip_add32(uip_connr->snd_nxt, uip_connr->len);            // 计算下一次发送的第一个字节的序列号
                                                              // uip_connr->len 用于记录本次发送的字节数
                                                              // 在第三次握手中uip_connr->len = 1
    if(BUF->ackno[0] == uip_acc32[0] && BUF->ackno[1] == uip_acc32[1] &&
       BUF->ackno[2] == uip_acc32[2] && BUF->ackno[3] == uip_acc32[3]) {
        uip_connr->snd_nxt[0] = uip_acc32[0];
        uip_connr->snd_nxt[1] = uip_acc32[1];
        uip_connr->snd_nxt[2] = uip_acc32[2];
        uip_connr->snd_nxt[3] = uip_acc32[3];
    }
}

uip_connr->rcv_nxt[0] = BUF->seqno[0];  // 用于第三次握手的ackno,将收到的
uip_connr->rcv_nxt[1] = BUF->seqno[1];  // 第二次握手中的seqno+1赋值给第三
uip_connr->rcv_nxt[2] = BUF->seqno[2];  // 次握手中的ackno
uip_connr->rcv_nxt[3] = BUF->seqno[3];
uip_add_rcv_nxt(1);       // uip_connr->rcv_nxt[3] = uip_connr->rcv_nxt[3]+1

2.被动连接中应用:
found_listen:
uip_connr->tcpstateflags = SYN_RCVD;  

uip_connr->snd_nxt[0] = iss[0];        // 第二次握手用的seqno赋值,该值是有咱定。
uip_connr->snd_nxt[1] = iss[1];
uip_connr->snd_nxt[2] = iss[2];
uip_connr->snd_nxt[3] = iss[3];

/* rcv_nxt should be the seqno from the incoming packet + 1. */
uip_connr->rcv_nxt[3] = BUF->seqno[3]; // 将对方第一次握手发送的seqno+1赋值给
uip_connr->rcv_nxt[2] = BUF->seqno[2]; // 第二次握手用的ackno
uip_connr->rcv_nxt[1] = BUF->seqno[1];
uip_connr->rcv_nxt[0] = BUF->seqno[0];
uip_add_rcv_nxt(1);

3.平时交互信息中的应用:
计算seqno的值跟主动链接中的应用-found:中主动链接部分代码重合,不在多说。
计算ackno:
uip_add_rcv_nxt(1 + uip_len);          // uip_connr->rcv_nxt+1+uip_len,其中uip_len是接收到的数据长度。

最后都要应用:
  BUF->ackno[0] = uip_connr->rcv_nxt[0];
  BUF->ackno[1] = uip_connr->rcv_nxt[1];
  BUF->ackno[2] = uip_connr->rcv_nxt[2];
  BUF->ackno[3] = uip_connr->rcv_nxt[3];
 
  BUF->seqno[0] = uip_connr->snd_nxt[0];
  BUF->seqno[1] = uip_connr->snd_nxt[1];
  BUF->seqno[2] = uip_connr->snd_nxt[2];
  BUF->seqno[3] = uip_connr->snd_nxt[3];

写入序号值。


====

http://blog.21ic.com/user1/4861/archives/2009/59995.html

你可能感兴趣的:(TCP中32位序号详解)