• neohope
    置顶
    2021-08-15
    四次挥手过程分析下【V5.8,正常流程】 5、客户端收到FIN包,子状态从TCP_FIN_WAIT2变为TCP_TIME_WAIT,返回ACK包 A、状态和子状态都为TCP_TIME_WAIT 【tcp_protocol.handler】tcp_v4_rcv-> ->if (sk->sk_state == TCP_TIME_WAIT) goto do_time_wait; ->do_time_wait: ->tcp_timewait_state_process ->->if (tw->tw_substate == TCP_FIN_WAIT2) ->->tw->tw_substate = TCP_TIME_WAIT; ->->inet_twsk_reschedule,重新设置回调时间 ->->return TCP_TW_ACK; B、返回ACK ->case TCP_TW_ACK: ->tcp_v4_timewait_ack(sk, skb); 6、服务端收到ACK包,状态从TCP_LAST_ACK变为TCP_CLOSE 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_state_process ->case TCP_LAST_ACK: ->tcp_done ->->tcp_set_state(sk, TCP_CLOSE); 7、客户端超时回调 A、超时时间定义 #define TCP_TIMEWAIT_LEN (60*HZ) #define TCP_FIN_TIMEOUT TCP_TIMEWAIT_LEN B、超时后,回调tw_timer_handler->inet_twsk_kill,进行inet_timewait_sock清理工作 C、没有找到状态变从TCP_TIME_WAIT变为TCP_CLOSE的代码 D、只看没调,有问题的,欢迎小伙伴告诉一下
    展开

    作者回复: 66666

    
    4
  • neohope
    置顶
    2021-08-15
    四次挥手过程分析上【V5.8,正常流程】 1、客户端主动断开连接,状态从TCP_ESTABLISHED变为TCP_FIN_WAIT1,发送FIN包给服务端 A、状态变为TCP_FIN_WAIT1 tcp_close->tcp_close_state ->tcp_set_state(sk, new_state[TCP_ESTABLISHED]),也就是TCP_FIN_WAIT1 B、发送FIN包 tcp_close->tcp_close_state ->tcp_send_fin 2、服务端收到FIN包,状态从TCP_ESTABLISHED变为TCP_CLOSE_WAIT,并返回ACK包 A、状态变为TCP_CLOSE_WAIT 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_established ->tcp_data_queue ->->tcp_fin ->->->inet_csk_schedule_ack; 安排ack ->->->sk->sk_shutdown |= RCV_SHUTDOWN; 模拟了close ->->->sock_set_flag(sk, SOCK_DONE); ->->->case TCP_ESTABLISHED: ->->->tcp_set_state(sk, TCP_CLOSE_WAIT); 修改状态 ->->inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW; ACS是否立即发送 B、发送ACK包 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_established【接上面】 ->tcp_ack_snd_check->__tcp_ack_snd_check->tcp_send_ack 3、客户端收到ACK包,状态从TCP_FIN_WAIT1变为TCP_FIN_WAIT2,然后被替换为状态TCP_TIME_WAIT,子状态TCP_FIN_WAIT2 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_state_process ->case TCP_FIN_WAIT1: ->tcp_set_state(sk, TCP_FIN_WAIT2); ->tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); ->->tw = inet_twsk_alloc(sk, tcp_death_row, state); ->->->tw->tw_state = TCP_TIME_WAIT; ->->->tw->tw_substate = TCP_FIN_WAIT2; ->->->timer_setup(&tw->tw_timer, tw_timer_handler, TIMER_PINNED); 4、服务端状态从TCP_CLOSE_WAIT变为TCP_LAST_ACK,发送FIN包 A、状态变为TCP_LAST_ACK tcp_close->tcp_close_state ->tcp_set_state(sk, new_state[TCP_CLOSE_WAIT]),也就是TCP_LAST_ACK B、发送FIN包 tcp_close->tcp_close_state ->tcp_send_fin
    展开
    
    2
  • neohope
    置顶
    2021-08-14
    三次握手过程分析【V5.8,正常流程】 1、客户端发起第一次握手,状态调变为TCP_SYN_SENT,发送SYN包 connect->__sys_connect->__sys_connect_file->【sock->ops->connect】tcp_v4_connect A、状态变化 ->tcp_set_state(sk, TCP_SYN_SENT); B、发送SYN ->tcp_connect->tcp_send_syn_data 2、服务端收到客户端的SYN包,初始化socket,状态从TCP_LISTEN变为TCP_NEW_SYN_RECV,发送第二次握手SYN_ACK包 A、收到连接,初始化socket accept->__sys_accept4->__sys_accept4_file->【sock->ops->accept】inet_csk_accept B、收到SYN,改变状态 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_state_process-> ->case TCP_LISTEN: ->[sock->ops->conn_request]tcp_v4_conn_request->tcp_conn_request ->->inet_reqsk_alloc ->->->ireq->ireq_state = TCP_NEW_SYN_RECV; C、发送SYN_ACK包 ->[sock->ops->conn_request]tcp_v4_conn_request->tcp_conn_request【和B路径一样】 ->->【af_ops->send_synack】tcp_v4_send_synack ->->->tcp_make_synack ->->->__tcp_v4_send_check 3、客户端收到SYN_ACK包,状态从TCP_SYN_SENT变为TCP_ESTABLISHED,并发送ACK包 A、收到SYN_ACK包 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_state_process ->case TCP_SYN_SENT: ->tcp_rcv_synsent_state_process->tcp_finish_connect ->->tcp_set_state(sk, TCP_ESTABLISHED); B、发送ACK包 ->tcp_rcv_synsent_state_process->tcp_send_ack->__tcp_send_ack 4、服务端收到ACK包,状态从TCP_NEW_SYN_RECV变为TCP_SYN_RECV【实际上是新建了一个sock】 【tcp_protocol.handler】tcp_v4_rcv-> ->if (sk->sk_state == TCP_NEW_SYN_RECV) ->tcp_check_req ->->【inet_csk(sk)->icsk_af_ops->syn_recv_sock】tcp_v4_syn_recv_sock->tcp_create_openreq_child->inet_csk_clone_lock ->->->inet_sk_set_state(newsk, TCP_SYN_RECV); 5、服务端状态从TCP_SYN_RECV变为TCP_ESTABLISHED 【tcp_protocol.handler】tcp_v4_rcv->tcp_v4_do_rcv->tcp_rcv_state_process ->case TCP_SYN_RECV: ->tcp_set_state(sk, TCP_ESTABLISHED); 只看没调,有问题的欢迎各位小伙伴指出。
    展开

    作者回复: 是的 总结到位

    
    3
  • pedro
    2021-08-09
    今天的问题不好回答,因为文中无明显三次握手的代码,而且三次握手的机制其实比较复杂,涉及到几个状态和几个队列之间的切换,笼统的 connect 和 accept 函数是说不清楚的,感兴趣可以看看这里: https://blog.csdn.net/tennysonsky/article/details/45621341 当然这些不能全信,所以还是得自己看linux内核代码,待我看了再来补充😂

    作者回复: 好的 期待

    共 3 条评论
    2
  • 王子虾
    2022-04-09
    老师,有一个问题,tcp在调用listen的时候,有全连接队列的概念,一般上限是128。但是问题是,我们比如实现单机百万链接的时候,一个server端的源组(server_ip+port),比如有65535个client,那会不会受限于这个全连接队列?

    作者回复: 会,但 linux可以修改 /proc/sys/net/core/somaxconn

    
    
  • ifelse
    2022-02-25
    nice

    作者回复: good

    
    
  • GeekCoder
    2021-10-24
    能讲讲epoll吗?

    作者回复: 本课程是os实现课程 不会讲到这个

    
    
  • pedro
    2021-08-09
    这里有一篇三次握手的源码图解:https://mp.weixin.qq.com/s/vlrzGc5bFrPIr9a7HIr2eA

    作者回复: 谢谢 老铁

    
    
  • MacBao
    2021-08-09
    服务器端处于listen状态,客户端connect发起TCP三次握手?
    
    1