标签:
把以前网络课的最长前缀匹配的作业重新写了下。简单说一下,输入输出要求如下,详细要求可见课程页面:https://kattis.csc.kth.se/problem?id=forwarding2
1.路由表以fib <prefix> <interface>格式给出,以换行符结束
2.报文以input <16进制ascii码> 红色为以太报文头,蓝色为目的ip地址
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
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\n", 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\n"); 51 } 52 else { 53 if (NULL == pCurrNode->pRightChild) { 54 pCurrNode->pRightChild = createNode(); 55 } 56 pCurrNode = pCurrNode->pRightChild; 57 DBG_PRINT("1 right\n"); 58 } 59 60 } 61 62 pCurrNode->iPort = iPort; 63 DBG_PRINT("%d port\n", 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\n", 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\n", 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\n", 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] = {‘\0‘}; 106 unsigned char aucBuf[BUFFER_SIZE] = {‘\0‘}; 107 int iLen = 0; 108 unsigned char ucTmp = ‘\0‘; 109 unsigned int uiPayload = 0, uiVersion = 0; 110 int i = 0; 111 int iRoute = 0, iIp = 0; 112 113 //读取路由表 114 while(0 != scanf("fib %d.%d.%d.%d/%d e%d\n", &a[0], &a[1], &a[2], &a[3], &iMask, &iPort)) { 115 DBG_PRINT("fib %d.%d.%d.%d/%d e%d\n", a[0], a[1], a[2], a[3], iMask, iPort); 116 iRoute = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0); 117 createRouteTree(iRoute, iMask, iPort); 118 } 119 120 //读取ip报文input标示 121 scanf("%s", aucTag); 122 if (0 == strncmp("input", aucTag, 5)) { 123 //读取ip报文16进制内容,注意格式%2hhx,一次读取一个字节 124 while((BUFFER_SIZE > iLen) && (1 == scanf("%2hhx", &ucTmp))) { 125 aucBuf[iLen] = ucTmp; 126 iLen++; 127 } 128 129 //获取协议类型和ip版本号 130 uiPayload |= (unsigned int)aucBuf[13]; 131 uiPayload |= (((unsigned int)aucBuf[12]) << 8); 132 uiVersion = aucBuf[14] >> 4; 133 134 //判断是否是ipv4报文 135 if(0x0800 != uiPayload) { 136 printf("Error: Not IPv4 payload\n"); 137 return 0; 138 } 139 else if (0x4 != uiVersion) { 140 printf("Error: Wrong IP version\n"); 141 return 0; 142 } 143 144 //判断长度是否合法 145 if(33 < iLen) { 146 DBG_PRINT("%d.%d.%d.%d\n", aucBuf[30],aucBuf[31],aucBuf[32],aucBuf[33]); 147 iIp = (aucBuf[30] << 24) | (aucBuf[31] << 16) | (aucBuf[32] << 8) | (aucBuf[33] << 0); 148 printf("e%d\n", getIpFwdPort(iIp)); 149 } 150 else { 151 printf("Error: Packet too short\n"); 152 } 153 154 } 155 return 0; 156 }
标签:
原文地址:http://www.cnblogs.com/letusrock/p/4321983.html