当服务器端接收到该报文后,处理流程和上边一样,会唤醒阻塞在该sock 上的接口,通知进程可以对该文件进行读写。
下面服务器端会调用 accept 函数,该函数的主要作用是从已经实现过三次握手的sock 中取出一个sock,来进行通信。
/* * This will accept the next outstanding connection. */ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err) { struct inet_connection_sock *icsk = inet_csk(sk); struct request_sock_queue *queue = &icsk->icsk_accept_queue; struct sock *newsk; struct request_sock *req; 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(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; } req = reqsk_queue_remove(queue);// 从已完成的连接队列中移除。 newsk = req->sk; sk_acceptq_removed(sk); if (sk->sk_protocol == IPPROTO_TCP && queue->fastopenq != NULL) { spin_lock_bh(&queue->fastopenq->lock); if (tcp_rsk(req)->listener) { /* We are still waiting for the final ACK from 3WHS * so can't free req now. Instead, we set req->sk to * NULL to signify that the child socket is taken * so reqsk_fastopen_remove() will free the req * when 3WHS finishes (or is aborted). */ req->sk = NULL; req = NULL; } spin_unlock_bh(&queue->fastopenq->lock); } out: release_sock(sk); if (req) __reqsk_free(req); return newsk;// 返回一个用于通信的 sock out_err: newsk = NULL; req = NULL; *err = error; goto out; }
至此双方的 sock 都处于 TCP_ESTABLISHED 状态,可以用于通信喽。