下面来看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;
}