sli*_*ter 1 c tcp linux-kernel
我试图了解如何在Linux内核版本2.6.33中实现TCP三次握手.
我从函数accept()开始,它引导我:
接受()==> sys_accept()==> sys_accept4()==> inet_accept()==> inet_csk_accept()
现在我被困在inet_csk_accept()中.
struct sock *inet_csk_accept(struct sock *sk, int flags, int *err)
{
struct inet_connection_sock *icsk = inet_csk(sk);
struct sock *newsk;
int error;
lock_sock(sk);
/* We need to make sure that this socket is listening,
* and that it has something pending.
*/
error = -EINVAL;
if (sk->sk_state != TCP_LISTEN)
goto out_err;
/* Find already established connection */
if (reqsk_queue_empty(&icsk->icsk_accept_queue)) {
long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
/* If this is a non blocking socket don't sleep */
error = -EAGAIN;
if (!timeo)
goto out_err;
error = inet_csk_wait_for_connect(sk, timeo);
if (error)
goto out_err;
}
newsk = reqsk_queue_get_child(&icsk->icsk_accept_queue, sk);
WARN_ON(newsk->sk_state == TCP_SYN_RECV);
out:
release_sock(sk);
return newsk;
out_err:
newsk = NULL;
*err = error;
goto out;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是程序何时进行
WARN_ON(newsk->sk_state == TCP_SYN_RECV);
Run Code Online (Sandbox Code Playgroud)
三方握手已经完成了吗?
服务器发送ACK的代码在哪里?
服务器从客户端确认ACK的代码在哪里?
或者如果我一开始就错了,那么在accpet()中是否实现了三次握手?
谢谢
TCP的实际套接字逻辑位于
net/ipv4/tcp_input.c
Run Code Online (Sandbox Code Playgroud)
插座的状态机位于功能中
int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
struct tcphdr *th, unsigned len)
Run Code Online (Sandbox Code Playgroud)
它实现所有套接字状态转换(包括三次握手).这个函数以这种方式调用:
tcp_v4_rcv => tcp_v4_do_rcv => tcp_rcv_state_process
Run Code Online (Sandbox Code Playgroud)
对于每个收到的TCP数据包.此调用由接口驱动程序(即网络适配器的驱动程序)启动.
accept()只有等待套接字状态从改变TCP_LISTEN到TCP_ESTABLISHED.并且状态TCP_LISTEN由设置listen().实际状态更改在tcp_rcv_state_process.中执行.
所以这个过程是异步的.呼叫accept()不直接导致呼叫tcp_rcv_state_process