WEB开发网
开发学院软件开发Java tcp connection setup的实现(二) 阅读

tcp connection setup的实现(二)

 2009-09-10 00:00:00 来源:WEB开发网   
核心提示: 最后是inet_csk_reqsk_queue_add,它用来把新的req加入到accept队列中. Java代码 staticinlinevoidinet_csk_reqsk_queue_add(structsock*sk,structrequest_sock*req,structsock*c

最后是inet_csk_reqsk_queue_add,它用来把新的req加入到accept队列中.

Java代码

static inline void inet_csk_reqsk_queue_add(struct sock *sk, 
     struct request_sock *req, 
     struct sock *child) 
{ 
 reqsk_queue_add(&inet_csk(sk)->icsk_accept_queue, req, sk, child); 
} 
 
 
static inline void reqsk_queue_add(struct request_sock_queue *queue, 
    struct request_sock *req, 
    struct sock *parent, 
    struct sock *child) 
{ 
 req->sk = child; 
 sk_acceptq_added(parent); 
///可以看到刚好就是request_sock_queue的rskq_accept_head与rskq_accept_tail保存accept队列. 
 if (queue->rskq_accept_head == NULL) 
 queue->rskq_accept_head = req; 
 else 
 queue->rskq_accept_tail->dl_next = req; 
 
 queue->rskq_accept_tail = req; 
 req->dl_next = NULL; 
}

然后再来看tcp_check_req的实现.

Java代码

struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, 
   struct request_sock *req, 
   struct request_sock **prev) 
{ 
 const struct tcphdr *th = tcp_hdr(skb); 
 __be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK); 
 int paws_reject = 0; 
 struct tcp_options_received tmp_opt; 
 struct sock *child; 
 
 tmp_opt.saw_tstamp = 0; 
...................................... 
///如果只有rst和syn域则发送一个rst给对端. 
if (flg & (TCP_FLAG_RST|TCP_FLAG_SYN)) { 
 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_ATTEMPTFAILS); 
 goto embryonic_reset; 
 } 
 
///如果是重传的syn,则重新发送syn和ack分组. 
 if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn && 
   flg == TCP_FLAG_SYN && 
   !paws_reject) { 
 req->rsk_ops->rtx_syn_ack(sk, req); 
 return NULL; 
 } 
 
 .......................................... 
 
///确定有设置ack分节. 
 if (!(flg & TCP_FLAG_ACK)) 
 return NULL; 
 
///这里主要处理TCP_DEFER_ACCEPT被设置的情况,如果它被设置,则丢掉这个包.(这是因为TCP_DEFER_ACCEPT会等待数据真正发过来才处理的,而不是最后一个ack发过来就处理) 
 if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && 
   TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { 
 inet_rsk(req)->acked = 1; 
 return NULL; 
 } 
 
///可以创建一个新的socket了.返回一个包含新创建的socket的request结构. 
 child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL); 
 if (child == NULL) 
 goto listen_overflow; 
.................................. 
#endif 
///创建成功,则在request_sock_queue的listen_opt中unlink掉这个req.也就是从半连接队列中删除这个req. 
 inet_csk_reqsk_queue_unlink(sk, req, prev); 
///修改对应的 qlen和qlen_young的值. 
 inet_csk_reqsk_queue_removed(sk, req); 
///最后加入到accept队列中.这里注意最终是将新的socket赋值给对应的req. 
 inet_csk_reqsk_queue_add(sk, req, child); 
 return child; 
 
listen_overflow: 
 if (!sysctl_tcp_abort_on_overflow) { 
 inet_rsk(req)->acked = 1; 
 return NULL; 
 } 
 
embryonic_reset: 
 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_EMBRYONICRSTS); 
 if (!(flg & TCP_FLAG_RST)) 
 req->rsk_ops->send_reset(sk, skb); 
 
 inet_csk_reqsk_queue_drop(sk, req, prev); 
 return NULL; 
}

上一页  3 4 5 6 7 8 9  下一页

Tags:tcp connection setup

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接