tcp connection setup的实现(二)
2009-09-10 00:00:00 来源:WEB开发网最后我们来看内核如何创建一个新的socket,tcp 协议使用tcp_v4_syn_recv_sock来实现,它做的其实很简单就是新建一个socket,并且设置状态为TCP_SYN_RECV(在 inet_csk_clone中),父socket继续处于listen状态,然后对新的socket进行一些赋值,然后对一些定时器进行初始化.这里定时器我们全部都略过了,以后会专门来分析tcp中的定时器.
最后从tcp_v4_hnd_req中返回,判断是否与父socket相等,然后调用tcp_child_process函数:
这个函数主要是完成最终的三次握手,将子socket设置为TCP_ESTABLISHED然后根据条件唤醒被accept阻塞的主socket:
Java代码
int tcp_child_process(struct sock *parent, struct sock *child,
struct sk_buff *skb)
{
int ret = 0;
int state = child->sk_state;
if (!sock_owned_by_user(child)) {
///完成最终的三次握手.
ret = tcp_rcv_state_process(child, skb, tcp_hdr(skb),
skb->len);
/* Wakeup parent, send SIGIO */
if (state == TCP_SYN_RECV && child->sk_state != state)
///唤醒阻塞的主socket.
parent->sk_data_ready(parent, 0);
} else {
/* Alas, it is possible again, because we do lookup
* in main socket hash table and lock on listening
* socket does not protect us more.
*/
sk_add_backlog(child, skb);
}
bh_unlock_sock(child);
sock_put(child);
return ret;
}
最后来分析下在tcp_rcv_state_process中的处理当前的TCP_SYN_RECV状态,它主要是为将要到来的数据传输做一些准备,设置一些相关域.:
Java代码
case TCP_SYN_RECV:
if (acceptable) {
tp->copied_seq = tp->rcv_nxt;
smp_mb();
///设置状态为TCP_ESTABLISHED.
tcp_set_state(sk, TCP_ESTABLISHED);
sk->sk_state_change(sk);
///这里的wake应该是针对epoll这类的
if (sk->sk_socket)
sk_wake_async(sk,
SOCK_WAKE_IO, POLL_OUT);
///设置期望接收的isn号,也就是第一个字节的序列和窗口大小.
tp->snd_una = TCP_SKB_CB(skb)->ack_seq;
tp->snd_wnd = ntohs(th->window) <<
tp->rx_opt.snd_wscale;
tcp_init_wl(tp, TCP_SKB_CB(skb)->ack_seq,
TCP_SKB_CB(skb)->seq);
.........................................................................
break;
Tags:tcp connection setup
编辑录入:爽爽 [复制链接] [打 印]更多精彩
赞助商链接