[奶妈の白嫖站]计算机网络 大作业 IP分组转发 C++/VS
奶妈の白嫖站
本程序以ppt上的例题图为例,书pdf151页上也有图和算法讲解
运行截图
程序代码 :本程序使用VS2015编写,支持中文变量,如软件不支持中文变量可使用wps进行批量查找替换(注意有些词组嵌套:如 路由表、路由表记录 等)
/*本程序使用VS2015编写,支持中文变量,如软件不支持中文变量可使用wps进行批量查找替换(注意有些词组嵌套:如 路由表、路由表记录 等)*/
/*本程序以ppt上的例题图为例,书pdf151页上也有图和算法讲解*/
#include<iostream>
#include<string>
using namespace std;
#define x 5 //假设路由表最多存x行路由表记录
#define y 5 //假设最多有y个路由器
/***************建立 路由表 和 路由表记录 结构体***************/
struct 路由表记录
{
string 目的网络地址 = "0"; //0用于打印时判断截止
string 子网掩码;
string 下一跳;
int 接口号; //转发到路由器R[接口号]
};
struct 路由表
{
路由表记录 info[x]; //设每个路由表最多有n行路由表记录
}R[y]; //相当于直接:路由表 R[y];
/***************打印 路由表 和 路由表记录 信息***************/
void 打印路由表(路由表 R)
{
cout << "目的网络地址\t子网掩码\t下一跳\t\t接口号\n";
for (int i = 0; i < x && R.info[i].目的网络地址 != "0"; i++)
{
cout << R.info[i].目的网络地址 << "\t" << R.info[i].子网掩码 << "\t" << R.info[i].下一跳 << "\t\t" << "R" << R.info[i].接口号+1 << "\n";
}
}
/***********内部手动部分定义 路由表 和 路由表记录 信息***********/
void 输入部分路由表(路由表 R[])
{
R[0].info[0].目的网络地址 = "128.30.33.0";
R[0].info[0].子网掩码 = "255.255.255.128";
R[0].info[0].下一跳 = "接口0";
R[0].info[0].接口号 = 0;
R[0].info[1].目的网络地址 = "128.30.33.128";
R[0].info[1].子网掩码 = "255.255.255.128";
R[0].info[1].下一跳 = "接口1";
R[0].info[1].接口号 = 0;
R[0].info[2].目的网络地址 = "128.30.36.0";
R[0].info[2].子网掩码 = "255.255.255.0";
R[0].info[2].下一跳 = "R2";
R[0].info[2].接口号 = 1;
R[1].info[0].目的网络地址 = "128.30.33.128";
R[1].info[0].子网掩码 = "255.255.255.128";
R[1].info[0].下一跳 = "接口0";
R[1].info[0].接口号 = 1;
R[1].info[1].目的网络地址 = "128.30.36.0";
R[1].info[1].子网掩码 = "255.255.255.0";
R[1].info[1].下一跳 = "接口1";
R[1].info[1].接口号 = 1;
R[1].info[2].目的网络地址 = "128.30.33.0";
R[1].info[2].子网掩码 = "255.255.255.128";
R[1].info[2].下一跳 = "R1";
R[1].info[2].接口号 = 0;
}
/***********制作 string地址 转 数组[4] 的工具函数***********/
void 字符串转数组(string address, int a[4])
{
a[0] = a[1] = a[2] = a[3] = 0;
int num = 0; //num指向数组a[]位置,i指向字符串address位数
int size = address.length();
for (int i = 0; i < size; i++)
{
while (isdigit(address[i])) //isdigit:如果是'0'-'9',则返回1
{
a[num] = a[num] * 10 + (address[i] - '0');
i++;
}
num++;
}
if (num != 4)
{
cout << "格式不对,转换出错\n";
}
}
/***********将 网络地址 和 子网掩码 相与***********/
string 相与(string ip1, string ip2)
{
int a[4], b[4], c[4];
字符串转数组(ip1, a);
字符串转数组(ip2, b);
for (int i = 0; i < 4; i++)
c[i] = a[i] & b[i];
char ip3[20];
//sprintf_s:将数据格式化输出到字符串(不加"_s"会报错)
sprintf_s(ip3, "%d.%d.%d.%d", c[0], c[1], c[2], c[3]);
string ip = ip3;
return ip;
}
/****************ip分组转发(初次转发)****************/
void ip转发(string 源地址, string 目的地址, string 源掩码, int 路由器号)
{
cout << "源地址:" << 源地址 << "\t源子网掩码:" << 源掩码 << "\t目的地址:" << 目的地址 << "\t路由器号:R" << 路由器号 <<endl;
/****************(1)判断是否 直接交付****************/
if (相与(源地址, 源掩码) == 相与(源掩码, 目的地址))
{
cout << "源主机和目的主机在同一个网络,直接交付\n";
return;
}
else
cout << "\n源主机和目的主机不在同一个网络,转到路由器R" << 路由器号 << "进行查找\n";
/****************(2)为否时 查找路由器****************/
int flag = 0; //定义一个检测是否交付成功的标志位flag
for (int i = 0; i < x; i++)
{
if (R[路由器号 - 1].info[i].目的网络地址 == 相与(R[路由器号 - 1].info[i].子网掩码, 目的地址))
{
if (R[路由器号 - 1].info[i].接口号 == 路由器号 - 1)
{
cout << "目的主机与路由器R" << 路由器号 << "直接相连,从" << R[路由器号 - 1].info[i].下一跳 << "直接交付\n";
return;
}
else
{
cout << "目的主机与路由器R" << 路由器号 << "非直接相连,从" << R[路由器号 - 1].info[i].下一跳 << "转发数据报\n";
/****************更新查找****************/
int 新路由器号 = R[路由器号 - 1].info[i].接口号+1;
ip转发(源地址, 目的地址, 源掩码, 新路由器号); //仅替换新路由器号即可
return;
}
}
flag++;
}
if (flag = x)
cout << "在已知的路由器表中没有找到交付地址\n";
}
int main()
{
输入部分路由表(R);
/***********输出已定义值的路由表***********/
for (int i = 0; i < y && R[i].info[0].目的网络地址 != "0"; i++)
{
cout << "——————————" << "路由表" << i + 1 << "的已知信息——————————\n";
打印路由表(R[i]);
}
/****************ip分组转发****************/
string 源地址, 目的地址, 源掩码;
int 路由器号;
cout << "请输入源地址:";
cin >> 源地址;
cout << "请输入源子网掩码:";
cin >> 源掩码;
cout << "请输入目的地址:";
cin >> 目的地址;
cout << "请输入本网络连接的路由器号R__:";
cin >> 路由器号;
ip转发(源地址, 目的地址, 源掩码, 路由器号);
/***************结束程序***************/
system("pause"); //获取一次回车,防止运行完瞬间退出
return 0;
}