在计算机网络中,路由表或称路由择域信息库(RIB)是一个存储在路由器或者联网计算机中的电子表格(文件)或类数据库。路由表存储着指向特定网络地址的路径(在有些情况下,还记录有路径的路由度量值)。路由表中含有网络周边的拓扑信息。路由表建立的主要目标是为了实现路由协议和静态路由选择。
在现代路由器构造中,路由表不直接参与数据包的传输,而是用于生成一个小型指向表,这个指向表仅仅包含由路由算法选择的数据包传输优先路径,这个表格通常为了优化硬件存储和查找而被压缩或提前编译。本文将忽略这个执行的详细情况而选择整个路径选择/传输信息子系统作为路由表来说明。
路由器的主要工作就是为经过路由器的每个数据包寻找一条最佳传输路径,并将该数据有效地传送到目的站点。由此可见,选择最佳路径的策略即路由算法是路由器的关键所在。为了完成这项工作,在路由器中保存着各种传输路径的相关数据——路由表(Routing Table),供路由选择时使用,表中包含的信息决定了数据转发的策略。打个比方,路由表就像我们平时使用的地图一样,标识着各种路线,路由表中保存着子网的标志信息、网上路由器的个数和下一个路由器的名字等内容。路由表可以是由系统管理员固定设置好的,也可以由系统动态修改,可以由路由器自动调整,也可以由主机控制。
路由来源1.静态路由表
由系统管理员事先设置好固定的路由表称之为静态(static)路由表,一般是在系统安装时就根据网络的配置情况预先设定的,它不会随未来网络结构的改变而改变。
2.动态路由表
动态(Dynamic)路由表是路由器根据网络系统的运行情况而自动调整的路由表。路由器根据路由选择协议(Routing Protocol)提供的功能,自动学习和记忆网络运行情况,在需要时自动计算数据传输的最佳路径。
路由器通常依靠所建立及维护的路由表来决定如何转发。路由表能力是指路由表内所容纳路由表项数量的极限。由于Internet上执行BGP协议的路由器通常拥有数十万条路由表项,所以该项目也是路由器能力的重要体现。
路由表项如下:
首先,路由表的每个项的目的字段含有目的网络前缀。其次,每个项还有一个附加字段,还有用于指定网络前缀位数的子网掩码(subnet mask).第三,当下一跳字段代表路由器时,下一跳字段的值使用路由的IP地址。
理解网际网络中可用的网络地址(或网络 ID)有助于路由决定。这些知识是从称为路由表的数据库中获得的。路由表是一系列称为路由的项,其中包含有关网际网络的网络 ID 位置信息。路由表不是对路由器专用的。主机(非路由器)也可能有用来决定优化路由的路由表。
请见代码
#include <stdio.h> #include <windows.h> #include <Iphlpapi.h> #pragma comment(lib, "Iphlpapi.lib") #pragma comment(lib, "WS2_32.lib") PMIB_IPFORWARDTABLE MyGetIpForwardTable(BOOL bOrder); void MyFreeIpForwardTable(PMIB_IPFORWARDTABLE pIpRouteTab); void PrintIpForwardTable(); int main() { PrintIpForwardTable(); return 0; } void PrintIpForwardTable() { PMIB_IPFORWARDTABLE pIpRouteTable = MyGetIpForwardTable(TRUE); if(pIpRouteTable != NULL) { DWORD i, dwCurrIndex; struct in_addr inadDest; struct in_addr inadMask; struct in_addr inadGateway; PMIB_IPADDRTABLE pIpAddrTable = NULL; char szDestIp[128]; char szMaskIp[128]; char szGatewayIp[128]; printf("Active Routes:\n\n"); printf(" Network Address Netmask Gateway Address Interface Metric\n"); for (i = 0; i < pIpRouteTable->dwNumEntries; i++) { dwCurrIndex = pIpRouteTable->table[i].dwForwardIfIndex; // 目的地址 inadDest.s_addr = pIpRouteTable->table[i].dwForwardDest; // 子网掩码 inadMask.s_addr = pIpRouteTable->table[i].dwForwardMask; // 网关地址 inadGateway.s_addr = pIpRouteTable->table[i].dwForwardNextHop; strcpy(szDestIp, inet_ntoa(inadDest)); strcpy(szMaskIp, inet_ntoa(inadMask)); strcpy(szGatewayIp, inet_ntoa(inadGateway)); printf(" %15s %16s %16s %16d %7d\n", szDestIp, szMaskIp, szGatewayIp, pIpRouteTable->table[i].dwForwardIfIndex, // 可以在此调用GetIpAddrTable获取索引对应的IP地址 pIpRouteTable->table[i].dwForwardMetric1); } MyFreeIpForwardTable(pIpRouteTable); } } PMIB_IPFORWARDTABLE MyGetIpForwardTable(BOOL bOrder) { PMIB_IPFORWARDTABLE pIpRouteTab = NULL; DWORD dwActualSize = 0; // 查询所需缓冲区的大小 if(::GetIpForwardTable(pIpRouteTab, &dwActualSize, bOrder) == ERROR_INSUFFICIENT_BUFFER) { // 为MIB_IPFORWARDTABLE结构申请内存 pIpRouteTab = (PMIB_IPFORWARDTABLE)::GlobalAlloc(GPTR, dwActualSize); // 获取路由表 if(::GetIpForwardTable(pIpRouteTab, &dwActualSize, bOrder) == NO_ERROR) return pIpRouteTab; ::GlobalFree(pIpRouteTab); } return NULL; } void MyFreeIpForwardTable(PMIB_IPFORWARDTABLE pIpRouteTab) { if(pIpRouteTab != NULL) ::GlobalFree(pIpRouteTab); }