首页 > 编程语言 > 写一个程序来模拟网桥功能

写一个程序来模拟网桥功能

时间:2022-11-16 22:56:32浏览次数:29  
标签:功能 模拟网 show 程序 网桥 new com id ttarticle

模拟实现网桥的转发功能,以从文件中读取帧模拟网桥从网络中收到一帧,即从两个文件中读入一系列帧,从第一个文件中读入一帧然后从第二个文件中再读入一帧,如此下去。对每一帧,显示网桥是否会转发,及显示转发表内容。
分析:用程序模拟网桥功能,可以假定用两个文件分别代表两个网段上的网络帧数据。而两个文件中的数据应具有帧的特征,即有目的地址,源地址和帧内数据。程序交替读入帧的数据,就相当于网桥从网段中得到帧数据。
对于网桥来说,能否转发帧在于把接收到的帧与网桥中的转发表相比较。判断目的地址后才决定是否转发。由此可见转发的关键在于构造转发表。这里转发表可通过动态生成。

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

标签:功能,模拟网,show,程序,网桥,new,com,id,ttarticle
From: https://www.cnblogs.com/snamd/p/16897846.html

相关文章

  • 安装软件和驱动程序需要微软数字签名无法安装?数字签名和数字证书区别
    1.安装软件和驱动程序需要微软数字签名无法安装方法一:1、以Win10为例,Win7同样适用,首先我们在键盘上同时按下“Windows键”+“R键”,调出运行,在运行中输入“gpedit.msc......
  • CUDA并行程序设计:GPU编程指南 电子书 pdf
    作者:(美)ShaneCook出版社:机械工业出版社原作名:CUDAProgramming:ADeveloper'sGuidetoParallelComputingwithGPUs译者:苏统华/李东/李松泽/魏通/主审......
  • 01-C++ 程序的编译和运行
    第一种方式将编译和链接分成两步。#编译,生成.o文件g++-chello.cpp#链接,生成可执行文件a.outg++hello.o#链接,生成可执行文件hellog++hello.o-ohello......
  • C++走向远洋——66(十五周阅读程序)
    */*Copyright(c)2016,烟台大学计算机与控制工程学院*Allrightsreserved.*文件名:text.cpp*作者:常轩*微信公众号:Worldhello*完成日期:2016年6月8日*版本号:V1.......
  • 微信小程序onreachbottom不触发
    写了一个触底加载的,但是不执行。onReachBottom:function(){...}究其原因是页面并没有超过100vh,导致不会执行。page{height:101vh;}如果你看细节的话,看一下......
  • 程序员转型架构师,推荐你读这几本书
    从CRUD的程序员,到系统的架构师,进阶推荐读这几本书。架构师书单分为两部分,第一部分是关于系统架构的方法论,包括领域驱动设计,微服务,整洁架构,第二部分介绍各大互联网大公司是如......
  • 小程序开发:用原生还是选框架(wepy/mpvue/uni-app/taro)?
    小程序开发:用原生还是选框架(wepy/mpvue/uni-app/taro)?自2017-1-9微信小程序诞生以来,历经2年多的迭代升级,已有数百万小程序上线,成为继Web、iOS、Android之后,第四大主流开发技......
  • 程序员必学的项目管理知识-敏捷开发
    敏捷开发的目的敏捷开发的目的是快速响应市场需求,举个例子,如果一个产品的开发周期为一年,如果等到尽善尽美再上线,那么时间周期是非常漫长的,在这个过程中,用户需求也会发生很......
  • 小程序4
    试图与逻辑学习目标:1.能够知道如何实现页面之间的跳转2.能够知道如何实现下拉刷新的效果3.能够知道如何实现上拉刷新的效果4.能够知道小程序中尝试用的生命周期函数......
  • 微信小程序: 子view的tap触发了父view的tap
    1、当子视图有事件,父也有事件tap,如何解决冲突。以下是代码:  子视图:1、catchtap2、hover-stop-propagation="true"这样就可以了,其它的不需要修改。 参考:https......