把以前网络课的最长前缀匹配的作业重新写了下。简单说一下,输入输出要求如下,详细要求可见课程页面:https://kattis.csc.kth.se/problem?id=forwarding2
1.路由表以fib <prefix> <interface>格式给出,以换行符结束
2.报文以input <16进制ascii码> 红色为以太报文头,蓝色为目的ip地址
Sample Input
fib 10.1.0.0/24 e1 fib 10.2.0.0/24 e2 fib 10.3.0.0/24 e3 fib 0.0.0.0/0 e1 input 0200 0000 0001 0200 0000 0011 0800 4500 0026 17d4 0000 ff01 8ffc 0a01 0002 0a02 0002 0000 e802 c04b 0004 3e89 339a 0786 d0ff 0009
Sample Output
e2
这里使用了二叉树路由查找的算法,一个ip地址为32bit,使用二叉树来表示路由表,最大深度为32,时间复杂度最大为32。左孩子节点不为空表示0,右孩子节点不为空表示1
1 //路由表元素节点 2 typedef struct node { 3 struct node *pLeftChild; 4 struct node *pRightChild; 5 int iPort; 6 }NODE;
代码如下,详细说明可见注释,需要注意的几点为:
1. scanf()函数返回的值为:
正确按指定格式输入变量的个数;也即能正确接收到值的变量个数。
scanf("%d%d", &a, &b);
如果a和b都被成功读入,那么scanf的返回值就是2
如果只有a被成功读入,返回值为1
如果a和b都未被成功读入,返回值为0
如果遇到错误或遇到end of file,返回值为EOF。
2.EOF如果通过键盘输入,在linux下使用ctl+d
3.以太报文包头长度为14字节(6字节目的mac,6字节源mac,2字节协议号),目的ip偏移为30字节,30~33一共4字节(不含vlan头的情况下)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #define BUFFER_SIZE 9000 6 #define DBG_PRINT if(1 == g_ulDbgPrint) printf 7 int g_ulDbgPrint = 0; 8 //路由表元素节点 9 typedef struct node { 10 struct node *pLeftChild; 11 struct node *pRightChild; 12 int iPort; 13 }NODE; 14 15 //路由表root 16 NODE *g_pRouteTree = NULL; 17 18 //创建节点函数 19 NODE *createNode() { 20 NODE *pNode = malloc(sizeof(NODE)); 21 pNode->pLeftChild = NULL; 22 pNode->pRightChild = NULL; 23 pNode->iPort = -1; 24 return pNode; 25 } 26 27 //创建路由表函数 28 void createRouteTree(int iRoute, int iMask, int iPort) { 29 int i = 0; 30 // 0 -- left, 1 -- right 31 int iLeftOrRight = 0; 32 static int iInitFlag = 0; 33 34 if (0 == iInitFlag) { 35 g_pRouteTree = createNode(); 36 iInitFlag = 1; 37 } 38 39 DBG_PRINT("input rounte: %8x, mask: %d, port: %d ", iRoute, iMask, iPort); 40 41 NODE *pCurrNode = g_pRouteTree; 42 for (i = 0; i < iMask; i++) { 43 iLeftOrRight = (iRoute >> (31 - i)) & 0x1; 44 45 if(0 == iLeftOrRight) { 46 if (NULL == pCurrNode->pLeftChild) { 47 pCurrNode->pLeftChild = createNode(); 48 } 49 pCurrNode = pCurrNode->pLeftChild; 50 DBG_PRINT("0 left "); 51 } 52 else { 53 if (NULL == pCurrNode->pRightChild) { 54 pCurrNode->pRightChild = createNode(); 55 } 56 pCurrNode = pCurrNode->pRightChild; 57 DBG_PRINT("1 right "); 58 } 59 60 } 61 62 pCurrNode->iPort = iPort; 63 DBG_PRINT("%d port ", iPort); 64 return; 65 } 66 67 //ip转发查找路由表函数 68 int getIpFwdPort(int iIp) { 69 int i = 0, iLeftOrRight = 0, iPort = -1; 70 NODE *pCurrNode = g_pRouteTree; 71 iPort = (-1 == pCurrNode->iPort)?iPort:pCurrNode->iPort; 72 73 DBG_PRINT("input ip: %8x ", iIp); 74 75 for (i = 0; i < 32; i++) { 76 iLeftOrRight = (iIp >> (31-i)) & 0x1; 77 78 if (0 == iLeftOrRight) { 79 if (NULL != pCurrNode->pLeftChild) { 80 pCurrNode = pCurrNode->pLeftChild; 81 iPort = (-1 == pCurrNode->iPort)?iPort:pCurrNode->iPort; 82 DBG_PRINT("0 go left, %d port ", iPort); 83 } 84 else { 85 break; 86 } 87 } 88 else { 89 if (NULL != pCurrNode->pRightChild) { 90 pCurrNode = pCurrNode->pRightChild; 91 iPort = (-1 == pCurrNode->iPort)?iPort:pCurrNode->iPort; 92 DBG_PRINT("1 go right, %d port ", iPort); 93 } 94 else { 95 break; 96 } 97 } 98 } 99 return iPort; 100 } 101 102 103 int main() { 104 int a[4] = {0}, iMask = 0, iPort = -1; 105 unsigned char aucTag[10] = {'