Linux tcp连接状态之SYNC 您所在的位置:网站首页 syn_received Linux tcp连接状态之SYNC

Linux tcp连接状态之SYNC

#Linux tcp连接状态之SYNC| 来源: 网络整理| 查看: 265

1、按tcp/ip协议的描述,tcp三次握手过程,tcp的状态迁移如下所示:

1)、客户端通过connect系统调用向处于LISTEN状态的服务端发送sync请求,客户端进入SYNC_SEND状态;

2)、服务端收到sync报文后,向客户端发送sync+ack报文,服务端进入SYNC_RECV状态;

3)、客户端收到sync+ack后,进入ESTABLISHED状态,并向服务端发送ack,服务端接收到ack后,进入ESTABLISHED状态。

(sys_connect) sync client(SYNC_SEND) ----------> server(LISTEN) sync+ack client(SYNC_SEND) server(ESTABLISHED)

2、但Linux的实现跟这里的描述并非完全一致,在Linux里,服务端收到sync报文并向客户端发送sync+ack后,并没有将自己置位SYNC_RECV状态,而是申请了一个request_sock,并将request_sock挂到sock的半连接队列里,等收到客户端的ack时,再从半连接队列里找到request_sock,并将其置位ESTABLISHED,然后挂到全连接队列中。

3、相关实现:

client端:

1)、client端调用connect系统调用发送sync报文,最终调用tcp_v4_connect,在tcp_v4_connect里通过tcp_set_state(sk, TCP_SYN_SENT)将sk状态置位SYNC_SNET; 2)、client收到server的sync+ack后,将状态置为ESTABLISHED。 tcp_v4_rcv     tcp_v4_do_rcv         tcp_rcv_state_process             tcp_rcv_synsent_state_process                 tcp_finish_connect                     tcp_set_state(sk, TCP_ESTABLISHED)

server端:

tcp_v4_rcv tcp_v4_do_rcv int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) { //收到sync包时,状态为TCP_LISTEN,条件成立 if (sk->sk_state == TCP_LISTEN) { //这里是从半连接队列的syn_table里找request_sock, //1、如果是sync报文,这里返回为空,跳转到tcp_rcv_state_process //在函数tcp_rcv_state_process里会创建一个新的request_sock,然后挂到半连接队列里 //具体流程:tcp_rcv_state_process->tcp_v4_conn_request->tcp_conn_request->inet_csk_reqsk_queue_hash_add //2、如果是client的ack报文,则这里返回的nsk为第1步创建的request_sock,并且在tcp_v4_hnd_req->tcp_check_req里 //将sk->sk_state状态置位SYNC_RECV,然后把request_sock从半连接队列里移除(tcp_check_req->inet_csk_reqsk_queue_removed) //具体流程:tcp_v4_hnd_req->tcp_check_req->tcp_v4_syn_recv_sock->tcp_create_openreq_child->inet_csk_clone_lock //(newsk->sk_state = TCP_SYN_RECV) struct sock *nsk = tcp_v4_hnd_req(sk, skb); if (!nsk) goto discard; //ack时找到的request_sock与sk不是同一个,条件成立 if (nsk != sk) { sock_rps_save_rxhash(nsk, skb); //该函数最终调用tcp_rcv_state_process,在tcp_rcv_state_process里判断sk->sk_state状态为SYNC_RECV, //并且收到的是ack报文,然后将状态置位ESTABLISHED。 if (tcp_child_process(sk, nsk, skb)) { rsk = nsk; goto reset; } return 0; } } else sock_rps_save_rxhash(sk, skb); if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) { rsk = sk; goto reset; } return 0; }

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有