模拟网桥工作原理

实验要求

模拟实现网桥的转发功能,以从文件中读取帧模拟网桥从网络中收到一帧,即从两个文件中读入一系列帧,从第一个文件中读入一帧然后从第二个文件中再读入一帧,如此下去。对每一帧,显示网桥是否会转发,及显示转发表内容。

要求:Windows或Linux环境下运行,程序应在单机上运行。

分析:用程序模拟网桥功能,可以假定用两个文件分别代表两个网段上的网络帧数据。而两个文件中的数据应具有帧的特征,即有目的地址,源地址和帧内数据。程序交替读入帧的数据,就相当于网桥从网段中得到帧数据。

对于网桥来说,能否转发帧在于把接收到的帧与网桥中的转发表相比较。判断目的地址后才决定是否转发。由此可见转发的关键在于构造转发表。这里转发表可通过动态生成。

原理

如果主机A向主机B发送数据,模拟网桥会出现的几种情况。

(1)学习:网桥通过查看帧的源地址了解到A在端口1,转发表中加入<A,1>。

(2)扩散:网桥并不知道B在何处,因此把帧向所有其它端口(除了本端口1)进行广播。

(3)转发:网桥通过查看帧的目的地址发现转发表中存在B的项<B,2>,因此该数据通过端口2转发出去。

(4)过滤:现在站点C向A发送数据,A、C在网桥同一个网段上。网桥也会收到该帧,查看源地址C,了解到C在端口1,加入表项<C,1>,同时目的地址A在转发表已经存在<A,1>,发现源和目的的端口号相同,说明在同个网段,因此不进行转发。

(5)老化:转发表的TTL每秒都增加,超过某个值则从数据库中清除,一般缺省的TTL设置为300秒。老化主要是考虑到网桥的内存有限、节点移动的情况。定期清除,像计时器一样。

本实验主要模拟了学习、扩散、转发和过滤这四种情况。网桥是工作在数据链路层,并能隔绝冲突域。

代码

#include <iostream>
#include <fstream>
#include <string>
#include <map>
using namespace std;

#define path1 "test1.txt"
#define path2 "test2.txt"

int main() {
	string src, dst, data;
	map<string, int> mp;
	map<string, int>::iterator  it;
	ifstream inf1(path1, ios::in);
	ifstream inf2(path2, ios::in);

	while (!inf1.eof() || !inf2.eof()) {
		if (!inf1.eof()) {
			it = mp.begin();
			cout << "转发表:" << endl;
			while (it != mp.end()) {
				cout << it->first << " " << it->second << endl;
				it++;
			}
			inf1 >> dst >> src >> data;
			cout << "网段1:" << endl;
			cout << "帧目的MAC地址:" << dst << " 源MAC地址:" << src << " 数据:" << data << endl;
			if (mp.count(src) == 0) {  // 该数据帧对应接口1(学习)
				mp[src] = 1;
			}
			if (mp.count(dst) == 1 && mp[src] == mp[dst]) {  // 同一端口,不转发(过滤)
				cout << "在同个网段,不转发!" << endl;
			}
			else if (mp.count(dst) == 1) {  // (转发)
				cout << "可以转发!转发接口为" << mp[dst] << "!" << endl;
			}
			else {  // (扩散)
				cout << "可以转发!广播除了接口" << mp[src] << "外的所有接口!" << endl;
			}
			cout << "----------------------------------------------------------------" << endl;
		}

		if (!inf2.eof()) {
			it = mp.begin();
			cout << "转发表:" << endl;
			while (it != mp.end()) {
				cout << it->first << " " << it->second << endl;
				it++;
			}
			inf2 >> dst >> src >> data;
			cout << "网段2:" << endl;
			cout << "帧目的MAC地址:" << dst << " 源MAC地址:" << src << " 数据:" << data << endl;
			if (mp.count(src) == 0) {  // 该数据帧对应接口2(学习)
				mp[src] = 2;
			}
			if (mp.count(dst) == 1 && mp[src] == mp[dst]) {  // 同一端口,不转发(过滤)
				cout << "在同个网段,不转发!" << endl;
			}
			else if (mp.count(dst) == 1) {  // (转发)
				cout << "可以转发!转发接口为" << mp[dst] << "!" << endl;
			}
			else {  // (扩散)
				cout << "可以转发!广播除了接口" << mp[src] << "外的所有接口!" << endl;
			}
			cout << "----------------------------------------------------------------" << endl;
		}
	}

	return 0;
}

/* 
注意:被读取文件中的帧格式是目的MAC地址在前,源MAC地址在后

test1:
22 11 000011101101010101010101010000
23 12 00001110110101010101010101
12 13 010101

test2:
11 22 000011101101010101010101010000
12 23 00001110110101010101010101
*/

Snipaste_2019-12-02_20-59-51

发布了100 篇原创文章 · 获赞 34 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_42780289/article/details/103357141