Linux内核分析 - 网络[十六]:TCP三次握手
查找到达[daddr, dport]的路由项,路由项的查找与更新与”路由表”章节所 述一样。要注意的是由于是作为客户端调用,创建socket后调用connect,因而saddr, sport都是0,同样在未查找路由前,要走 的出接口oif也是不知道的,因此也是0。在查找完路由表后(注意不是路由缓存),可以得知出接口,但并未存储到sk中。因此插 入的路由缓存是特别要注意的:它的键值与实际值是不相同的,这个不同点就在于oif与saddr,键值是[saddr=0, sport=0, daddr, dport, oif=0],而缓存项值是[saddr, sport=0, daddr, dport, oif]。 tmp = ip_route_connect(&rt, nexthop, inet->inet_saddr, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, IPPROTO_TCP, inet->inet_sport, usin->sin_port, sk, 1); if (tmp < 0) { if (tmp == -ENETUNREACH) IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); return tmp; } 通过查找到的路由项,对inet进行赋值,可以看到,除了sport,都赋予了值,sport的选择复杂点,因为它要随机从 未使用的本地端口中选择一个。 if (!inet->inet_saddr) inet->inet_saddr = rt_rt_src; inet->inet_rcv_addr = inet->inet_saddr; …… inet->inet_dport = usin->sin_port; inet->inet_daddr = daddr; 状态从CLOSING转到TCP_SYN_SENT,也就是我们熟知的TCP的状态转移图。 tcp_set_state(sk, TCP_SYN_SENT); 插入到bind链表中 err = inet_hash_connect(&tcp_death_row, sk); //== > __inet_hash_connect() 当 snum==0时,表明此时源端口没有指定,此时会随机选择一个空闲端口作为此次连接的源端口。low和high分别表示可用端口的下 限和上限,remaining表示可用端口的数,注意这里的可用只是指端口可以用作源端口,其中部分端口可能已经作为其它socket 的端口号在使用了,所以要循环1~remaining,直到查找到空闲的源端口。 if (! snum) { inet_get_local_port_range(&low, &high); remaining = (high - low) + 1; …… for (i = 1; i <= remaining; i++) { ……// choose a valid port } } (编辑:PHP编程网 - 黄冈站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |