简单模拟网桥对mac地址的转发,开始转发表为空,动态生成转发表

模拟网段示意图

透明网桥算法c++实现_源地址

算法实现

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include <vector>
using namespace std;

//网桥登记信息
struct Data{
string macAddr;//收到帧的源mac地址 用一个英文字母模拟(和书上一样) 但也可以任意字符串
int port;//收到帧进入该网桥的接口号
string time;//收到帧进入网桥的时间
Data(){macAddr="",port=0,time="";}//初始化
};

//转发表 模拟3个网段 两个转发表 此处接口号还模拟网段号
vector<Data> Table[2];//转发表 0 两张转发表 接口1 转发表0 接口2 接口3 转发表1 接口4

//接口与网桥(转发表的映射) 1->0 2->0 3->1 4->1
int portBrige[]={0,0,0,1,1};

//剩下的转发端口 1->3 2->0 3->5 4->2 一个网桥有几个端口这应该是写死的 此处模拟的网桥仅2个端口
int RemainingPort[]={-1,3,0,5,2};

//获取当前时间
string getNowTime(){
time_t timep;//时间结构体变量
struct tm *p;
char *wday[]={"星期天","星期一","星期二","星期三","星期四","星期五","星期六"};
time(&timep);//获取当前时间
p=localtime(&timep);//获取当地时间 并按现在的时间日期来表示
char a[100];
sprintf(a,"%d年%d月%d日 %s %02d:%02d:%02d",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday,
wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);
string ans=a;
return ans;
}

//转发表table里找目标地址macAdde 源站地址也要接收 因为每次写表的就是源站地址信息
int Find(vector<Data> &table,Data Start,Data End){//转发表用引用 否则转发记录无法保存

//写或者更新源站地址信息 每次都要执行 写到哪都一样
int i;
for(i=0;i<table.size();i++){
if(table[i].macAddr==Start.macAddr){
table[i].time=getNowTime();//找到了 更新时间
break;
}
}
if(i==table.size()){
//没找到源站 写入
Start.time=getNowTime();
table.push_back(Start);//加入一条记录 源站信息
}

//查找目的站
for(i=0;i<table.size();i++){
if(table[i].macAddr==End.macAddr){
table[i].time=getNowTime();//更新时间
return table[i].port;//返回找到的端口
}
}
//没找到 返回-1
return -1;
}

//打印转发表
void Print(vector<Data> table){
printf("地址\t接口\t更新时间\n");
for(int i=0;i<table.size();i++){
cout<<table[i].macAddr<<"\t"<<table[i].port<<"\t"<<table[i].time<<endl;
}
cout<<endl;
}



void startSend(Data s,Data e){
int n=portBrige[s.port];
int x=Find(Table[n],s,e);
if(x==-1){
cout<<"网桥"<<n<<"未找到"<<e.macAddr<<".已转发给除"<<s.port<<"以外所有接口\n";
//转到其他端口
s.port=RemainingPort[s.port];
if(s.port>=1&&s.port<=4){//在模拟的两个网桥范围内
startSend(s,e);
return;
}else{
cout<<"在模拟范围以外继续查找!"<<endl;
}
}else{
//找到了 一直查表查下去即可 直接打印转发表
if(x==s.port){//端口号相同
cout<<"找到了但是端口号相同,也即"<<s.macAddr<<"与"<<e.macAddr
<<"在同一个网段,不需要经过网桥转发,直接丢弃!"<<endl;
}else{
cout<<"找到了,已从端口"<<x<<"转发此帧"<<endl;
}
}
}

int main(){
cout<<"透明网桥模拟\n";
Data Start,End;

cout<<"输入源地址:";cin>>Start.macAddr;
cout<<"输入接口号:";cin>>Start.port;//1 2 3 4
cout<<"输入目的地址:";cin>>End.macAddr;

while(1){
startSend(Start,End);

cout<<"转发表0"<<endl;
Print(Table[0]);
cout<<"转发表1"<<endl;
Print(Table[1]);
cout<<"输入源地址:";cin>>Start.macAddr;
cout<<"输入接口号:";cin>>Start.port;//1 2 3 4
cout<<"输入目的地址:";cin>>End.macAddr;
}
return 0;
}

运行结果:

透明网桥模拟
输入源地址:A
输入接口号:1
输入目的地址:F
网桥0未找到F.已转发给除1以外所有接口
网桥1未找到F.已转发给除3以外所有接口
在模拟范围以外继续查找!
转发表0
地址 接口 更新时间
A 1 2019年4月10日 星期三 20:12:35

转发表1
地址 接口 更新时间
A 3 2019年4月10日 星期三 20:12:35

输入源地址:B
输入接口号:1
输入目的地址:F
网桥0未找到F.已转发给除1以外所有接口
网桥1未找到F.已转发给除3以外所有接口
在模拟范围以外继续查找!
转发表0
地址 接口 更新时间
A 1 2019年4月10日 星期三 20:12:35
B 1 2019年4月10日 星期三 20:12:40

转发表1
地址 接口 更新时间
A 3 2019年4月10日 星期三 20:12:35
B 3 2019年4月10日 星期三 20:12:40

输入源地址:C
输入接口号:3
输入目的地址:Z
网桥1未找到Z.已转发给除3以外所有接口
在模拟范围以外继续查找!
转发表0
地址 接口 更新时间
A 1 2019年4月10日 星期三 20:12:35
B 1 2019年4月10日 星期三 20:12:40

转发表1
地址 接口 更新时间
A 3 2019年4月10日 星期三 20:12:35
B 3 2019年4月10日 星期三 20:12:40
C 3 2019年4月10日 星期三 20:12:57

输入源地址:F
输入接口号:4
输入目的地址:A
找到了,已从端口3转发此帧
转发表0
地址 接口 更新时间
A 1 2019年4月10日 星期三 20:12:35
B 1 2019年4月10日 星期三 20:12:40

转发表1
地址 接口 更新时间
A 3 2019年4月10日 星期三 20:13:05
B 3 2019年4月10日 星期三 20:12:40
C 3 2019年4月10日 星期三 20:12:57
F 4 2019年4月10日 星期三 20:13:05

输入源地址:A
输入接口号:1
输入目的地址:F
网桥0未找到F.已转发给除1以外所有接口
找到了,已从端口4转发此帧
转发表0
地址 接口 更新时间
A 1 2019年4月10日 星期三 20:13:09
B 1 2019年4月10日 星期三 20:12:40

转发表1
地址 接口 更新时间
A 3 2019年4月10日 星期三 20:13:09
B 3 2019年4月10日 星期三 20:12:40
C 3 2019年4月10日 星期三 20:12:57
F 4 2019年4月10日 星期三 20:13:09

输入源地址:A
输入接口号:1
输入目的地址:B
找到了但是端口号相同,也即A与B在同一个网段,不需要经过网桥转发,直接丢弃!
转发表0
地址 接口 更新时间
A 1 2019年4月10日 星期三 20:13:38
B 1 2019年4月10日 星期三 20:13:38

转发表1
地址 接口 更新时间
A 3 2019年4月10日 星期三 20:13:09
B 3 2019年4月10日 星期三 20:12:40
C 3 2019年4月10日 星期三 20:12:57
F 4 2019年4月10日 星期三 20:13:09

输入源地址: