C++模擬網橋轉發功能


題目:寫一個程序來模擬網橋功能。

模擬實現網橋的轉發功能,以從文件中讀取幀模擬網橋從網絡中收到一幀,即從兩個文件中讀入一系列幀,從第一個文件中讀入一幀然后從第二個文件中再讀入一幀,如此下去。對每一幀,顯示網橋是否會轉發,及顯示轉發表內容。

  • 要求:Windows或Linux環境下運行,程序應在單機上運行。
  • 分析:
    1. 用程序模擬網橋功能,可以假定用兩個文件分別代表兩個網段上的網絡幀數據。而兩個文件中的數據應具有幀的特征,即有目的地址,源地址和幀內數據。程序交替讀入幀的數據,就相當於網橋從網段中得到幀數據。
    2. 對於網橋來說,能否轉發幀在於把接收到的幀與網橋中的轉發表相比較。判斷目的地址后才決定是否轉發。由此可見轉發的關鍵在於構造轉發表。這里轉發表可通過動態生成。

本地數據樣式

注意文檔中不要有多余的空格,換行。每個字符串中間是一個tab鍵不是8個空格鍵。
第一次運行時,轉發表可以什么內容都沒有

  • 網段一

  • 網段二

  • 轉發表

分析

  1. 理解好網橋的功能,代碼實現並不困難(當然我的代碼並不是完全符合網橋的邏輯的,是一個最簡單的網橋功能實現);
  2. 這個實驗讓我們實現網橋的自學習和轉發幀
    • 自學習:查找轉發表中與收到幀的源地址有無相匹配的項目。
      -如果有,更新原有項目(簡單的代碼實現就更新一下時間);
      -如果沒有,新增一個項目。
    • 轉發幀:查找轉發表中與收到幀的目的地址有無相匹配的項目。
      - 如果有,按轉發表給出接口進行轉發;
      - 如果沒有,通過所有接口進行轉發;
      - 若轉發表給出的接口就是該幀進入網橋的接口,丟棄該幀。

程序流程圖

代碼

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <Windows.h>
#include <cstdio>
 #include <time.h>
using namespace std;

//獲取string類型的本地時間
string GetSystemTimeStr()
{
	struct tm t;   //tm結構指針
	time_t now;  //聲明time_t類型變量
	time(&now);      //獲取系統日期和時間
	localtime_s(&t, &now);   //獲取當地日期和時間
	string time;
	time.append(to_string(t.tm_year+1900));
	time.append(".");
	time.append(to_string(t.tm_mon+1));
	time.append(".");
	time.append(to_string(t.tm_mday));
	time.append("  ");
	time.append(to_string(t.tm_hour));
	time.append(":");
	time.append(to_string(t.tm_min));
	time.append(":");
	time.append(to_string(t.tm_sec));
	return time;
}

//查表,自學習並進行轉發
bool forword(map<string, pair<string, string>>& forwordingTable, string frame, int flag) {
	//如果是讀到文件中的第一行,返回
	if (frame == "source\tdestn\tdata") return false;
	cout << "網橋接口" << flag << "接收到幀數據" << endl;
	//網橋解析幀數據
	int firstTabIndex = frame.find_first_of("\t");
	int lastTabIndex = frame.find_last_of("\t");
	//源地址
	string source = frame.substr(0, firstTabIndex);
	//目的地址
	string destination = frame.substr(firstTabIndex + 1, lastTabIndex - firstTabIndex - 1);
	//幀內數據
	string data = frame.substr(lastTabIndex + 1, frame.size() - lastTabIndex);

	//幀離開源地址,到達網橋(按道理這語句應該在最上面,但是要用到幾個變量只能放在這里)
	cout << "PC" << source << " send data to " << "PC" << destination << ": " << data << endl;
	//查轉發表
	//自學習,先用源地址更新轉發表
	map<string, pair<string, string>>::iterator iter = forwordingTable.find(source);
	//表中沒有匹配,新增項目
	if (iter == forwordingTable.end()) {
		pair<string, string> save(to_string(flag), GetSystemTimeStr());
		forwordingTable.insert(pair<string, pair<string, string>>(source, save));
	}
	//表中有匹配,更新項目
	else forwordingTable[source].second = GetSystemTimeStr();
	//轉發幀,判斷轉發表中是否有目的地址
	iter = forwordingTable.find(destination);
	//沒有有目的地址,通過所有接口進行轉發;有目的地址,按給定接口進行轉發
	if (iter == forwordingTable.end()) cout << "轉發表中無PC" << destination << "的信息,網橋通過所有接口進行轉發" << endl;
	else if (forwordingTable[destination].first == to_string(flag)) cout << "PC" << source << "和PC" << destination << "在同一網段下,丟棄該幀數據" << endl;
	else cout << "從接口" << flag << "處進行轉發" << endl;
	//幀離開網橋網橋,到達目的地址
	cout << "PC" << destination << " receive data from " << source << ": " << data << endl << endl;
	return true;
}

int main() {
	//讀取兩網段和轉發表文件
	ifstream segment1File("segment1.txt");
	if (!segment1File.is_open()) {
		cout << "segmeng1文件打開失敗!" << endl;
		return 1;
	}
	ifstream segment2File("segment2.txt");
	if (!segment2File.is_open()) {
		cout << "segmeng2文件打開失敗!" << endl;
		return 1;
	}
	ifstream forwordingTableFileRead("forwordingTable.txt");
	if (!forwordingTableFileRead.is_open()) {
		cout << "forwordingTable文件打開失敗!" << endl;
		return 1;
	}

	//用地圖存起來轉發表
	map<string, pair<string,string>> forwordingTable;
	string row;
	while (getline(forwordingTableFileRead, row))
	{
		//忽略第一行標題
		if (row == "PC\tsegment\ttime") continue;
		//找到制表符位置
		int firstTabIndex = row.find_first_of('\t');
		int lastTabIndex = row.find_last_of("\t");
		//獲取map的key和value,插入map
		string key = row.substr(0, firstTabIndex);
		string value = row.substr(firstTabIndex +1, lastTabIndex - firstTabIndex - 1);
		string time = row.substr(lastTabIndex + 1, row.size() - lastTabIndex);
		pair <string, string> save(value, time);
		forwordingTable.insert(pair<string, pair<string,string>>(key, save));
	}

	//幀數據
	string frame;
	//交替讀入標志
	int flag = 1;
	//網橋開始工作
	while (!segment1File.eof() || !segment2File.eof()) {
		if (flag == 1) {
			if (!segment1File.eof()) {
				//讀網段一中的一行
				getline(segment1File, frame);
				if(!forword(forwordingTable, frame, flag)) continue;
			}
			//交替
			flag = 2;
		}
		if (flag == 2) {
			if (!segment2File.eof()) {
				//讀網段二中的一行
				getline(segment2File, frame);
				if (!forword(forwordingTable, frame, flag)) continue;
			}
			//交替
			flag = 1;
		}
	}

	//更新轉發表到本地
	ofstream forwordingTableFileWrite("forwordingTable.txt");
	if (!forwordingTableFileWrite.is_open()) {
		cout << "forwordingTable文件打開失敗!" << endl;
		return 1;
	}
	forwordingTableFileWrite << "PC\tsegment\ttime" << endl;
	for (auto mapIndex : forwordingTable) {
		forwordingTableFileWrite << mapIndex.first << "\t" << mapIndex.second.first << "\t" << mapIndex.second.second<<endl;
	}

	//完成工作,關閉文件
	segment1File.close();
	segment2File.close();
	forwordingTableFileRead.close();
	forwordingTableFileWrite.close();
	return 0;
}

結果截圖

  • 第一次轉發表中沒有任何信息

  • 第二次轉發表中已經有了全部信息


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM