zoukankan      html  css  js  c++  java
  • ip转发二叉树查找方法c实现

    把以前网络课的最长前缀匹配的作业重新写了下。简单说一下,输入输出要求如下,详细要求可见课程页面: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] = {''};
    106     unsigned char aucBuf[BUFFER_SIZE] = {''};
    107     int iLen = 0;
    108     unsigned char ucTmp = '';
    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
    ", &a[0], &a[1], &a[2], &a[3], &iMask, &iPort)) {
    115         DBG_PRINT("fib %d.%d.%d.%d/%d e%d
    ", 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
    ");
    137             return 0;
    138         }
    139         else if (0x4 != uiVersion) {
    140             printf("Error: Wrong IP version
    ");
    141             return 0;
    142         }
    143 
    144         //判断长度是否合法
    145         if(33 < iLen) {
    146             DBG_PRINT("%d.%d.%d.%d
    ", 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
    ", getIpFwdPort(iIp));
    149         }
    150         else {
    151             printf("Error: Packet too short
    ");
    152         }
    153 
    154     }
    155     return 0;
    156 }
  • 相关阅读:
    ECMAScript 2016(ES7) 知多少
    PyCharm连接远程服务器
    PyCharm远程开发和调试
    SecureCRT使用帮助
    NLP文本相似度
    程序控制结构--案例
    程序控制结构--选择结构
    程序控制结构--条件表达式
    Python序列结构--集合
    Python序列结构--字典
  • 原文地址:https://www.cnblogs.com/letusrock/p/4321983.html
Copyright © 2011-2022 走看看