加入收藏 | 设为首页 | 会员中心 | 我要投稿 源码门户网 (https://www.92codes.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux内核分析 - 网络[十六]:TCP三次握手

发布时间:2016-09-28 12:48:07 所属栏目:Linux 来源:站长网
导读:副标题#e# 内核:2.6.34 TCP是应用最广泛的传输层协议,其提供了面向连接的、可靠的字节流服务,但 也正是因为这些特性,使得TCP较之UDP异常复杂,还是分两部分[创建与使用]来进行分析。这篇主要包括TCP的创建及三次握手 的过程。 编程时一般用如下语句创建

状态TCP_SYN_RECV的设置可能比较奇怪,按照TCP 的状态转移图,在服务端收到SYN报文后变迁为TCP_SYN_RECV,但看到在实现中收到ACK后才有了状态TCP_SYN_RECV,并且马上会 变为TCP_ESTABLISHED,所以这个状态变得无足轻重。这样做的原因是listen和accept返回的socket是不同的,而只有真正连接 建立时才会创建这个新的socket,在收到SYN报文时新的socket还没有建立,就无从谈状态变迁了。这里同样是一个平衡的存在 ,你也可以在收到SYN时创建一个新的socket,代价就是无用的socket大大增加了。

child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL);     
if (child == NULL)     
 goto listen_overflow;     
inet_csk_reqsk_queue_unlink(sk, req, prev);     
inet_csk_reqsk_queue_removed(sk, req);     
inet_csk_reqsk_queue_add(sk, req, child);

tcp_child_process()

如果此时sock: child被用户进程锁住了,那么就先添加到backlog中__sk_add_backlog(),待解锁时再处理backlog上的sock;如果此时没有被 锁住,则先调用tcp_rcv_state_process()进行处理,处理完后,如果child状态到达TCP_ESTABLISHED,则表明其已就绪,调用 sk_data_ready()唤醒等待在isck_accept_queue上的函数accept()。

if (!

sock_owned_by_user(child)) {
 ret = tcp_rcv_state_process(child, skb, tcp_hdr(skb), skb->len);
 if (state == TCP_SYN_RECV && child->sk_state != state)
  parent->sk_data_ready(parent, 0);
} else {
 __sk_add_backlog(child, skb);
}

tcp_rcv_state_process()处理各个状态上socket的情况。下面是处于TCP_SYN_RECV的代码段,注意此时传入函数的 sk已经是新创建的sock了(在tcp_v4_hnd_req()中),并且状态是TCP_SYN_RECV,而不再是listen socket,在收到ACK后,sk状态 变迁为TCP_ESTABLISHED,而在tcp_v4_hnd_req()中也已将sk插入到了icsk_accept_queue上,此时它就已经完全就绪了,回到 tcp_child_process()便可执行sk_data_ready()。

case TCP_SYN_RECV:     
 if (acceptable) {
  ……     
  tcp_set_state(sk, TCP_ESTABLISHED);
  sk->sk_state_change(sk);
  ……
  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)->seq);
  ……
}

最后总结三次握手的过程

Linux内核分析 - 网络[十六]:TCP三次握手

(编辑:源码门户网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读