tcp connection setup的实现(一)
2009-09-10 00:00:00 来源:WEB开发网int inet_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
unsigned char old_state;
int err;
lock_sock(sk);
err = -EINVAL;
///判断状态(非连接状态)以及socket类型.
if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM)
goto out;
old_state = sk->sk_state;
///状态必须为close或者listen.
if (!((1 << old_state) & (TCPF_CLOSE | TCPF_LISTEN)))
goto out;
/* Really, if the socket is already in listen state
* we can only allow the backlog to be adjusted.
*/
///非listen状态,需要我们处理.
if (old_state != TCP_LISTEN) {
err = inet_csk_listen_start(sk, backlog);
if (err)
goto out;
}
///将backlog赋值给sk_max_ack_backlog,也就是完全连接队列最大值.
sk->sk_max_ack_backlog = backlog;
err = 0;
out:
release_sock(sk);
return err;
}
然后来看inet_csk_listen_start的实现.
它的主要工作是新分配一个listen socket,将它加入到inet_connection_sock的icsk_accept_queue域的listen_opt中.然后对当前使用端口进行判断.最终返回:
Java代码
int inet_csk_listen_start(struct sock *sk, const int nr_table_entries)
{
struct inet_sock *inet = inet_sk(sk);
struct inet_connection_sock *icsk = inet_csk(sk);
///新分配一个listen socket.
int rc = reqsk_queue_alloc(&icsk->icsk_accept_queue, nr_table_entries);
if (rc != 0)
return rc;
///先将这两个ack_backlog赋值为0.
sk->sk_max_ack_backlog = 0;
sk->sk_ack_backlog = 0;
inet_csk_delack_init(sk);
/* There is race window here: we announce ourselves listening,
* but this transition is still not validated by get_port().
* It is OK, because this socket enters to hash table only
* after validation is complete.
*/
///设置状态.
sk->sk_state = TCP_LISTEN;
///get_port上面已经分析过了.这里之所以还要再次判断一下端口,是为了防止多线程,也就是另一个线程在我们调用listen之前改变了这个端口的信息.
if (!sk->sk_prot->get_port(sk, inet->num)) {
//端口可用的情况,将端口值付给sport,并加入到inet_hashinfo(上面已经分析过)的listening_hash hash链表中.
inet->sport = htons(inet->num);
sk_dst_reset(sk);
///这里调用__inet_hash实现的.
sk->sk_prot->hash(sk);
return 0;
}
///不可用,则返回错误.
sk->sk_state = TCP_CLOSE;
__reqsk_queue_destroy(&icsk->icsk_accept_queue);
return -EADDRINUSE;
}
Tags:tcp connection setup
编辑录入:爽爽 [复制链接] [打 印]更多精彩
赞助商链接