下面来看TCP重组过程当中的三次握手:
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
完成三次握手后,开始传送数据。
/*******************************************************************************************************************
第一次握手
*******************************************************************************************************************/
if (!(a_tcp = find_stream(this_tcphdr, this_iphdr, &from_client))) { /*是三次握手的第一个包*/ /*tcp里流不存在时:且tcp数据包里的(syn=1 && ack==0 && rst==0)时,添加一条tcp流*/ /*tcp第一次握手*/ if ((this_tcphdr->th_flags & TH_SYN) && !(this_tcphdr->th_flags & TH_ACK) && !(this_tcphdr->th_flags & TH_RST)) /*并且没有收到th_rest 包*/ add_new_tcp(this_tcphdr, this_iphdr);/*节点加入链表中*/ /*第一次握手完毕返回*/ return; } if (from_client) { /*从client --> server的包*/ snd = &a_tcp->client; rcv = &a_tcp->server; } else {/* server --> client的包 */ rcv = &a_tcp->client; snd = &a_tcp->server; }
/*******************************************************************************************************************
第二次握手
*******************************************************************************************************************/
/*tcp 三次握手, SYN ==1,ACK==1,tcp第二次握手(server -> client的同步响应)*/ if ((this_tcphdr->th_flags & TH_SYN)) { if (from_client || a_tcp->client.state != TCP_SYN_SENT || a_tcp->server.state != TCP_CLOSE || !(this_tcphdr->th_flags & TH_ACK)) return; /*第二次回应包的ACK 值为第一个包的序列号+1,在初始化的时候已经加一*/ if (a_tcp->client.seq != ntohl(this_tcphdr->th_ack)) return; /*第二个包服务端赋值*/ /*a_tcp 中服务端赋值,*/ a_tcp->server.state = TCP_SYN_RECV; a_tcp->server.seq = ntohl(this_tcphdr->th_seq) + 1; a_tcp->server.first_data_seq = a_tcp->server.seq; a_tcp->server.ack_seq = ntohl(this_tcphdr->th_ack); a_tcp->server.window = ntohs(this_tcphdr->th_win); /*对于tcp 选项的赋值*/ //初始化客户端和服务器的时间截 if (a_tcp->client.ts_on) { a_tcp->server.ts_on = get_ts(this_tcphdr, &a_tcp->server.curr_ts); if (!a_tcp->server.ts_on) a_tcp->client.ts_on = 0; } else a_tcp->server.ts_on = 0; //初始化窗口大小 if (a_tcp->client.wscale_on) { a_tcp->server.wscale_on = get_wscale(this_tcphdr, &a_tcp->server.wscale); if (!a_tcp->server.wscale_on) { a_tcp->client.wscale_on = 0; a_tcp->client.wscale = 1; a_tcp->server.wscale = 1; } } else { a_tcp->server.wscale_on = 0; a_tcp->server.wscale = 1; } /*第二次握手完毕,返回*/ return; }