写一个程序来模拟网桥功能。
一、实验内容
模拟实现网桥的转发功能,以从文件中读取帧模拟网桥从网络中收到一帧,即从两个文件中读入一系列帧,从第一个文件中读入一帧然后从第二个文件中再读入一帧,如此下去。对每一帧,显示网桥是否会转发。
要求:
Windows或Linux环境下运行,程序应在单机上运行。
分析:
用程序模拟网桥功能,可以假定用两个文件分别代表两个网段上的网络帧数据。而两个文件中的数据应具有帧的特征,即有目的地址,源地址和帧内数据。程序交替读入帧的数据,就相当于网桥从网段中得到帧数据,当然如果模拟的数据量比较少,也可以用两个数组代替两个文件存放帧数据,同样达到代表两个网段上的帧数据的效果。对于网桥来说,能否转发帧在于把接收到的帧与网桥中的转发表相比较。判断目的地址后才决定是否转发。由此可见转发的关键在于构造转发表。这里转发表可通过动态生成。
二、程序流程图
三、参考代码
package bridge;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Scanner;
public class Bridge {
@SuppressWarnings("unused")
public static void main(String[] args) {
try(FileReader f1 = new FileReader("f1.txt");
BufferedReader br1 = new BufferedReader(f1);
FileReader f2 = new FileReader("f2.txt");
BufferedReader br2 = new BufferedReader(f2)) {
Bridge bridge = new Bridge();
Frame frame = bridge.new Frame();
while(br1 != null || br2 != null) {
if(br1 != null ) {
frame.dstmac = br1.readLine();
frame.srcmac = br1.readLine();
if(frame.dstmac != null && frame.srcmac !=null) {
bridge.rec(frame, "m0");
}else {
break;
}
}else {
f1.close();
}
if(br2 != null) {
frame.dstmac = br2.readLine();
frame.srcmac = br2.readLine();
if(frame.srcmac != null && frame.dstmac != null) {
bridge.rec(frame, "m1");
}else {
break;
}
}else {
f2.close();
}
}
}catch(Exception e) {
e.printStackTrace();
}
}
int max = 128;
static int num = 0;
String[][] table = new String[max][2]; //转发表:[地址][接口]
class Frame{
String dstmac; //目的mac地址
String srcmac; //源mac地址
}
void show() {
System.out.println("\t地址\t\t接口");
int i,j;
for(i=0;i<max-1;i++)
{
for(j=0;j<2;j++) {
if(table[i][j] != null) {
System.out.print(table[i][j]+"\t");
}
}
System.out.println();
if(table[i][1] == null) break;
}
System.out.println("------------------------------------------");
}
int srcinside(Frame frame) { //判断源mac地址是否在转发表内,自学习
int i;
for(i=0;i<=num;i++)
{
if(frame != null && frame.srcmac.equals(table[i][0])) return 1; //在内
}
return 0; //不在
}
int dstinside(Frame frame) //判断目的mac地址是否在转发表内
{
int i;
for(i=0;i<=num;i++)
if(frame != null && frame.dstmac.equals(table[i][0])) return i; //返回记录行
return -1; //不在
}
void update(Frame frame, String inter)
{
table[num][0] = frame.srcmac; //添加地址
table[num][1] = inter; //添加接口
num++;
}
void rec(Frame frame,String inter){
if(frame.srcmac != null && frame.dstmac != null) {
System.out.println("从"+inter+"接口收到的帧,源地址为:"+frame.srcmac+",目的地址:"+frame.dstmac);
if(dstinside(frame) == -1) {
System.out.println("转发表内无该条目!从除"+inter+"的其余接口转发!");
if(srcinside(frame) == 0) {
update(frame, inter); //自学习
}
}
else {
if(srcinside(frame) == 0) update(frame, inter); //自学习
System.out.print("转发表内找到匹配条目!");
if(table[dstinside(frame)][1] == inter ) {
System.out.println("由于在同一个接口,直接丢弃!");
}
else {
System.out.print("从"+table[dstinside(frame)][1]+"接口转发!");
System.out.println();
}
}
show();
}
}
}
四、运行结果
五、总结
首先先设置一个二维字符串数组作为转发表,转发表内容包括地址以及转发接口。其次,建立一个帧结构,帧内容包括:目的mac地址、源mac地址。最后,在实现的时候,为了编程简单和便于理解,文件中设置了帧的目的mac地址和源mac地址为一个字母。就通过不断从文件中交替,每次读取两行数据,与转发表进行比较。若转发表存在,则判断目的mac地址是否与源mac地址,是否在同一接口,相同则丢弃,不同则转发。若转发表不存在,则通过自学习,简单地将源mac地址和接口信息记录到转发表内,并转发到其他接口。