linux网络协议栈(六)传输层 (2)UDP协议 2)connect

来源:互联网 发布:梦幻2卖号网络异常 编辑:程序博客网 时间:2024/06/11 04:11
6.2.2.2.3、connect对端地址:

bind方法让内核知道了这条传输通道sock的接收地址是什么,而connect方法是告诉内核这条传输通道sock的发送地址是哪里,connect方法的重点是如下两条:

1、             接收报文无需考虑报文是怎么过来的,但是发送报文则必须考虑这个报文能不能发送出去,确切的说就是报文的目的地址,从本机是否可达,即路由表中是否能达到这个目的IP,这需要在路由表中有匹配条目;

2、             如果在发送报文之前不使用connect,那么发送时必须使用sendto系统调用而不是send,因为必须指定目的地址否则内核不知道报文该发向何方;而如果使用connect系统调用,那么传输通道sock将记录路由条目,之后就可以一直使用该路由条目

下面一步步介绍connect方法:


1、和bind类似,调用相应套接字类型的ops,实际为inet_dgram_connect函数,这个函数需要注意一下,它将检查IP描述符的源端口是否绑定过,如果没有,将由内核随机找一个当前可用的端口号为其绑定,如下图:


可见,当检测到没有bind过源端口时(!inet_sk(sk)->num),将调用inet_autobind为其随机找到一个当前可用端口号进行绑定;

2、然后是调用传输层ops的connect方法,注意和bind不同,对于connect方法,不同的传输层协议有不同的connect方法,这是因为TCP协议的connect方法除了记录目的地址,还涉及TCP协议相关的内容,这里只考虑UDP协议,其connect方法为函数ip4_datagram_connect,如下图:


2、这里就是在做本节起始描述的connect的第一个重点:寻找由本地去往发送目的地的路由,这是connect方法的核心,根据源目IP、源目端口、出接口等信息寻找路由,注意出接口等信息一般不存在也无需考虑,对于单播报文最重要的就是其通过目的IP和目的端口查找路由;对于目的IP为组播的情况,需要根据源IP和出接口寻找路由,这里暂不考虑组播的情况;

调用函数ip_route_connect寻找路由,其实就是把源目IP、源目端口、出接口等信息组合为一个匹配项查找路由,路由方面内容参加第五章;可见,一定要确保能找到这个路由,确切的说目的IP一定得可达;


找到路由后,说明这个目的地址是可达的,然后把路由条目指示的目的地址记录在IP描述符中,注意目的IP一定是路由条目指示的目的地址,因为往往目的地址是要通过路由转发而不是直接一跳可达,比如访问192.168.36.106,那么下一跳是网关地址192.168.10.1,那么这里就要把网关地址192.168.10.1记录在IP描述符中,而不是192.168.36.106;目的端口则直接记录即可,最终把路由信息存储在传输通道sock中(sk_dst_set(sk, &rt->u.dst)),方便以后发送时直接使用,无需再查路由表;

同时还要把sock的状态迁移至TCP_ESTABLISHED,这也是因为要适配TCP协议;

至此,内核已经知道了该传输通道sock的目的地址(记录在IP描述符的daddr、dport字段),并且传输通道sock还记录了该路由(sk->sk_dst_cache),方便以后发送时直接使用

对于UDP协议,在服务器bind了接收地址,客户端bind了接收地址和发送地址后,客户端就可以向服务器发送报文了,同时服务器也可以接收到报文了,下面描述报文的收发;
0 0