模拟实现网桥的转发功能,以从文件中读取帧模拟网桥从网络中收到一帧,即从两个文件中读入一系列帧,从第一个文件中读入一帧然后从第二个文件中再读入一帧,如此下去。对每一帧,显示网桥是否会转发,及显示转发表内容。
分析:用程序模拟网桥功能,可以假定用两个文件分别代表两个网段上的网络帧数据。而两个文件中的数据应具有帧的特征,即有目的地址,源地址和帧内数据。程序交替读入帧的数据,就相当于网桥从网段中得到帧数据。
对于网桥来说,能否转发帧在于把接收到的帧与网桥中的转发表相比较。判断目的地址后才决定是否转发。由此可见转发的关键在于构造转发表。这里转发表可通过动态生成。
2、 编写一个计算机程序用来计算一个文件的16位效验和。最快速的方法是用一个32位的整数来存放这个和。记住要处理进位(例如,超过16位的那些位),把它们加到效验和中。
要求:
以命令行形式运行:check_sum infile。其中check_sum为程序名,infile为输入数据文件名。
输出:数据文件的效验和
附:效验和(checksum)
参见RFC1071 - Computing the Internet checksum
原理:
把要发送的数据看成16比特的二进制整数序列,并计算他们的和。若数据字节长度为奇数,则在数据尾部补一个字节的0以凑成偶数。
例子:16位效验和计算,下图表明一个小的字符串的16位效验和的计算。
为了计算效验和,发送计算机把每对字符当成16位整数处理并计算效验和。如果效验和大于16位,那么把进位一起加到最后的效验和中。
实验步骤、记录和结果
1、 写一个程序来模拟网桥功能。
模拟实现网桥的转发功能,以从文件中读取帧模拟网桥从网络中收到一帧,即从两个文件中读入一系列帧,从第一个文件中读入一帧然后从第二个文件中再读入一帧,如此下去。对每一帧,显示网桥是否会转发,及显示转发表内容。
分析:用程序模拟网桥功能,可以假定用两个文件分别代表两个网段上的网络帧数据。而两个文件中的数据应具有帧的特征,即有目的地址,源地址和帧内数据。程序交替读入帧的数据,就相当于网桥从网段中得到帧数据。
对于网桥来说,能否转发帧在于把接收到的帧与网桥中的转发表相比较。判断目的地址后才决定是否转发。由此可见转发的关键在于构造转发表。这里转发表可通过动态生成。
为了更加深入的了解网桥的功能,本实验设计了一个四个接口的网桥,连在网桥上面的主机数目为12。其拓扑结构如下如图:
程序分析:
模拟网桥实验首先设置一个List存放在每个接口发出的帧的组合,再设计一个Interface类表示每个接口的接口号和链接在这个接口的主机号(为了方便表示,接口号用阿拉伯数字表示,主机号用大写英文字母表示)。然后又设置一个List存放这网桥的接口。然后遍历要发送的帧,读进来的帧进行分析, 先判别源地址是否存在于网桥转发表中, 若果在则进入第一个循环模块, 再判别目标地址是否在转发表中,最后输出数据由哪个接口转发。如果源地址不在转发表中, 要把这个源地址和所对应接口写入网桥的转发表中, 在进行其他判别。由此可见转发的关键在于构造转发表,这里转发表是动态生成的。
程序流程图如下图:
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class Bridge {
public static void main(String[] args) {
List<String> str = new ArrayList<String>(); //存放所有传输的帧
List<Interface> str1 = new ArrayList<Interface>(); //记录转发表的内容
creatTxtFile(); //创建txt文件,并且写入数据
readTxtFile(str); //读取txt文件
System.out.println("开始监听:");
for (int i = 0; i < str.size(); i++) {
String[] str2 = str.get(i).split(" ");
str1.add(new Interface(i));
for (int j = 0; j < str2.length; j++) {
//检查网桥是否记录源地址
if (!str1.get(i).host.contains(String.valueOf(str2[j].charAt(0)))) { //检查接口是否记录这个主机
str1.get(i).host.add(str2[j].charAt(0) + "");
}
//检查网桥是否记录目的地址
boolean isExist = false;
int k;
for (k = 0; k < str1.size(); k++) {
if (str1.get(k).host.contains(String.valueOf(str2[j].charAt(1)))) {
isExist = true;
break;
}
}
if (isExist) {
if (i == k) {
System.out.println("目的地址在同一个接口,不转发。");
} else
System.out.println(str2[j].charAt(0)+"与接口" + String.valueOf(k + 1)+"的"+str2[j].charAt(1)+"进行通讯。");
} else {
System.out.println("转发表没有此目的地址,向其他接口进行广播。");
}
}
}
System.out.println("停止监听。");
for (int i = 0; i < str1.size(); i++) {
System.out.println("与接口:" + String.valueOf(i + 1) + "连接的主机有:" + str1.get(i).host);
}
}
// 创建.txt文件,放置转发记录,文件中每一帧以空格分开,第一个字母代表源地址,第二个字母代表目的地址
public static void creatTxtFile() {
File file1 = new File("./", "1.txt");
try {
if (!file1.exists()) {
file1.createNewFile();
}
FileWriter fw = new FileWriter("1.txt", false);
fw.write("AC BH AB CD BJ CK AG \nDA LC LD DK LJ DL ");
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
File file2 = new File("./", "2.txt");
try {
if (!file2.exists()) {
file2.createNewFile();
}
FileWriter fw = new FileWriter("2.txt", false);
fw.write("EF EL EA EF FH GK GE \nHB ID HI JA JC KE JK KG IA IJ IC JF");
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 从.txt文件中读出要发送的帧
public static void readTxtFile(List<String> str) {
InputStreamReader reader;
BufferedReader br;
String line = null;
try {
reader = new InputStreamReader(new FileInputStream("./1.txt")); // 建立一个输入流对象reader
br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言
while ((line = br.readLine()) != null) {
//System.out.println(line);
str.add(line);
}
reader = new InputStreamReader(new FileInputStream("./2.txt")); // 建立一个输入流对象reader
br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言
while ((line = br.readLine()) != null) {
//System.out.println(line);
str.add(line);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// 接口
class Interface {
int number; //网桥的接口号
List<String> host; //连接在这个接口上的主机
public Interface(int num) {
number = num;
host = new ArrayList();
}
}
程序结果截图如下:
开发中遇到的问题:
每个网桥的接口数目不确定,每个接口数目不确定也不相等,如果单纯使用二维数组存储网桥的转发表可能会溢出或则空间浪费。为了更方便的记录网桥的接口,因此设计了interface类,然后使用List存储。
待解决的问题:
在查找转发表的时候使用的是遍历查找,这样会浪费很多时间的开销,特别对于那些经常互相发送消息的主机,希望能够使用一些合适的算法减少其中的查找时间。
2、 编写一个计算机程序用来计算一个文件的16位效验和。最快速的方法是用一个32位的整数来存放这个和。记住要处理进位(例如,超过16位的那些位),把它们加到效验和中。
原理:
为了计算效验和,发送计算机把每对字符当成16位整数处理并计算效验和。如果效验和大于16位,那么把进位一起加到最后的效验和中。
程序流程图:
程序源代码:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class Check_sum {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
System.out.println("Please input file name:infile");
String firStr = String.valueOf(sc.next());
System.out.println(firStr);
while (!firStr.equals("infile")) {
System.out.println("Wrong command! Please input again!");
firStr = sc.next();
}
checkSum(firStr);
}
public static String checkSum(String firStr) throws IOException {
String result = new String();
firStr = firStr + ".txt";
File file = new File(firStr); //创建新文件infile
if (!file.exists()) {
file.createNewFile();
FileWriter fw = new FileWriter(file, true);
BufferedWriter bw = new BufferedWriter(fw);
bw.write("Hello world."); //新文件写入信息
bw.flush();
bw.close();
fw.close();
}
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String str = br.readLine(); //读取文件的信息
byte[] buff = str.getBytes();
int byteNum = buff.length; //文本含有的字节数
String choose = (byteNum % 2 == 0 ? "偶数" : "奇数"); //判断字节数是奇数还是偶数
int num = 0;
if (choose.equals("偶数")) {
num = (int) Math.ceil(buff.length / 2);
result = getString(result, buff);
}
if (choose.equals("奇数")) {
num = (int) Math.ceil(buff.length / 2) + 1;
result = getString(result, buff);
result += "00";
}
int[] ten = new int[100];
String[] b = new String[100];
for (int i = 0; i < num; i++) {
b[i] = result.substring(i * 4, i * 4 + 4);
}
int notNullSize = 0;
for (int i = 0; i < b.length; i++) { //获取加法项的非空项数
if (b[i] != null) {
notNullSize++;
}
}
for (int i = 0; i < notNullSize; i++) {
ten[i] = Integer.parseInt(b[i], 16); //将非空加法项转化为10进制的数
}
int sum = 0; //计算和的十进制
int carry = 0; //进位数
String checkSum = null; //十六进制的校验和
for (int i = 0; i < notNullSize; i++) {
//将非空加法项转化为10进制的数
sum += ten[i];
checkSum = Long.toHexString(sum);
int judge = Integer.parseInt(checkSum, 16);
if (judge > 65535) {
carry = 1;
sum = judge - 65536 + carry;
}
}
System.out.println("效验和为:0x" + checkSum);
return null;
}
private static String getString(String result, byte[] buff) {
for (int i = 0; i < buff.length; i++) {
String hex = Integer.toHexString(buff[i] & 0xFF);
if (hex.length() == 1) {
hex = "0" + hex;
}
result += hex.toUpperCase();
}
return result;
}
}
weibo.com/ttarticle/p/show?id=2309404836484284023040
weibo.com/ttarticle/p/show?id=2309404836484283761039
weibo.com/ttarticle/p/show?id=2309404836484287954957
weibo.com/ttarticle/p/show?id=2309404836484296605736
weibo.com/ttarticle/p/show?id=2309404836484309188758
weibo.com/ttarticle/p/show?id=2309404836484308926711
weibo.com/ttarticle/p/show?id=2309404836484313383243
weibo.com/ttarticle/p/show?id=2309404836484321509765
weibo.com/ttarticle/p/show?id=2309404836484321771849
weibo.com/ttarticle/p/show?id=2309404836484321772126
weibo.com/ttarticle/p/show?id=2309404836484334092901
weibo.com/ttarticle/p/show?id=2309404836484338286671
weibo.com/ttarticle/p/show?id=2309404836484342743210
weibo.com/ttarticle/p/show?id=2309404836484346938250
weibo.com/ttarticle/p/show?id=2309404836484355326132
weibo.com/ttarticle/p/show?id=2309404836484355326208
weibo.com/ttarticle/p/show?id=2309404836484380492714
weibo.com/ttarticle/p/show?id=2309404836484418241482
weibo.com/ttarticle/p/show?id=2309404836484438949957
weibo.com/ttarticle/p/show?id=2309404836484472766699
weibo.com/ttarticle/p/show?id=2309404836484485350164
weibo.com/ttarticle/p/show?id=2309404836484506059303
weibo.com/ttarticle/p/show?id=2309404836484531487005
结果截图:
遇到的问题:
开始没有注意到效验和大于16位的情况。这种情况下要把进位一起加到最后的效验和中。比如271FA这个超过了16位,那么我想要的校验和是71FA+2。71FA可以通过271FA&OXffff,这样保留了后16位。2 是271FA超出16位的那部分,超出可以通过位运算得到,也就是右移16位可以得到超出16位的那些。271FA右移16位就是2了。
————————————————
版权声明:本文为CSDN博主「jacka03」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43644231/article/details/107347086