短接通信实现

版权声明:本文为博主原创文章,未经博主允许不得转载哦!!! https://blog.csdn.net/lph188/article/details/84375561

课题:短接通信功能实现

            (1)短接通信问题之一——短接隧道的解决方案

       (2)短接通信问题之二——重复路径的解决方案

       (3)短接通信问题之三 ——循环路径的解决方案

本文对短接通信的三个问题(短接隧道问题、重复路径问题、循环路径问题)提出解决方案,并进行代码实现。

我们解决的网络体系结构是树状体系结构,拓扑图如图1所示。

                                                                             图 1 树状体系结构拓扑图

通过分析网络结构拓扑图,我们知道严格的树状结构使网络连接缺少灵活性,并可能使相邻用户接入网之间的通信要绕道高层节点域,从而增长传输路径、不必要的增加高层信道的通信量负载,故使用短接通信来克服这些缺陷。使用短接通信的同时,又会出现短接隧道问题、重复路径问题、循环路径问题等问题,下面我们将详细介绍这些问题,并进行解决。

开发环境:Visual Studio 2017

开发语言:C、C++

一、搭建网络结构

首先,我们先根据图1中的网络结构图进行构建两颗树的结构,一颗以A1为根节点,一颗以A为根节点。在构造之前我们先对每个节点域进行设计,一个节点域包括:前缀地址、交换地址、名称、ip、外部交换地址表、短接表、数据等。

typedef struct Node {
		int ex_len;//前缀地址位数
		int trans_len;//交换地址位数
		char *name;//节点域的名字
		char *ip;//ip
		struct extrans_table extable[table_length];//外部交换地址表
		int len_extable;//外部交换地址表长度
		struct shortcircuit_table shorttable[table_length];//短接表
		int len_shorttable;//短接表长度
		trans_data *data;//数据指针
		struct Node *father;//父节点
		struct Node *chlidren[chlidren_length];//孩子节点
		struct Node *out_node;//短接指针
}Node;

外部交换地址表包括外部逻辑信道编号和下一个节点域。

typedef struct extrans_table {//外部逻辑信道编号
        char *Lport;
	struct Node *next;
}extrans_table;

短接表包括节点的前缀地址和短接节点的ip。

typedef struct shortcircuit_table {//前缀地址
	char *exIp;
	char *nextip;
}shortcircuit_table;

数据中包括节点域的ip、数据内容和数据包装指针。

typedef struct trans_data {
		const char *des_ip;
		const char *data;
		const char *in_desip;
}trans_data;

在设计完所有结构体和表等信息后,我们使用初始化函数进行构造树状网络体系结构:

int init(Node *A1, Node *A, Node *Ha, Node *Hb, Node *Hc)
   {
		Node *C1 = (struct Node*)malloc(sizeof(struct Node));
		Node *F1 = (struct Node*)malloc(sizeof(struct Node));
		Node *B = (struct Node*)malloc(sizeof(struct Node));
		Node *C = (struct Node*)malloc(sizeof(struct Node));
		Node *D = (struct Node*)malloc(sizeof(struct Node));
		Node *E = (struct Node*)malloc(sizeof(struct Node));
		Node *G = (struct Node*)malloc(sizeof(struct Node));
		Node *H = (struct Node*)malloc(sizeof(struct Node));
		Node *M = (struct Node*)malloc(sizeof(struct Node));
Node *L = (struct Node*)malloc(sizeof(struct Node));
……
A1->name = "A1";
		A1->ip = "1";
		A1->ex_len = 1;
		A1->trans_len = 1;
		A1->chlidren[0] = C1;
		A1->extable[0].Lport = "1";
		A1->extable[0].next = C1;
		A1->len_extable = 1;
		A1->len_shorttable = 0;
……
}

我们使用手动创建树状结构,并手动初始化好每一个节点域,对于每个节点的ip前缀分配如下表:

节点

Ip前缀

节点

Ip前缀

节点

Ip前缀

A1

1

A

0

I

0101

B1

10

B

000

J

000000

C1

11

C

001

K

000001

D1

100

D

010

L

01000

E1

101

E

00000

M

01001

F1

110

F

00001

Hb

010000

G1

111

G

00010

Hc

000100

Ha

1100

H

0100

 

 

于是,我们就创建了基本的网状数据结构,接下来,我们将针对出现的三个问题进行分析和解决。

二、短接隧道实现

问题描述:短接隧道问题可以归结于短接信道上数据反向传递问题。以图1中的拓扑图为例,我们首先对外部短接信道(C1—E)在C1节点域中配置了E和A的地址前缀。当主机Ha要与主机Hb通信时,Ha发给Hb的数据包可以经过路径Ha -> F1 -> C1 -> E -> B -> A -> D -> H -> L -> Hb到达,但是从Hb发给Ha的数据包却找不到主机Ha。

问题分析:从Hb发给Ha的数据包却找不到主机Ha,是因为信宿地址是主机Ha的地址,要经过F1才能到达,但是数据包从Hb -> L -> H -> D -> A后,根据节点域按地址字段交换数据包的规则,节点域A并不能将数据包下行送到E去,而是认为Ha的地址超出了本树状网的范围,认为不可达。

解决方案:封装成内部报文,在临时信宿E撤销封装。首先,我们在节点域A中配置C1的前缀地址,然后选择一个临时信宿结点E,在结点A中对配置结点E的前缀地址映射表;在结点A中,把数据进行封装操作(利用E的前缀地址作为数据包的信宿地址,换句话说,此时的信宿地址就是结点E),下行到结点E时,进行解封操作(将数据包恢复成从Hb发出时的样子取出真正的信宿地址Ha),然后继续转发数据包,转发时,先查询短接信道表,发现表中有C1的表项,并与数据包信宿地址Ha的地址前缀相同,于是就把数据包从短接信道上送到C1,接着数据包就正常的传送到主机Ha。

伪代码实现:

void short_tunnel(Node *A) {
	A->shorttable[0].exIp = "11";
	A->shorttable[0].nextip = "00000";
	A->len_shorttable = 1;
}
int init(Node *A1, Node *A, Node *Ha, Node *Hb, Node *Hc) {
……
    E->shorttable[0].exIp = "11";
    E->shorttable[0].nextip = NULL;
    E->len_shorttable = 1;
……
}
//封装操作
void find_path(Node *user) {
……
if (user->data->in_desip != NULL) {
	int temp = 0;
	int count = 0;
	if (strcmp(user->data->in_desip, user->ip) == 0) {
		user->data->in_desip = NULL;
		user->out_node->data = user->data;
		user = user->out_node;
		continue;
	}
……
}

运行结果:如图2所示。

                                                                          图 2 短接隧道运行结果

三、重复路径实现

问题描述:重复路径问题就是在短接信道上数据传送时会重复通过某些结点域。以图1中的拓扑图为例,我们首先对外部短接信道(C1—E)在C1节点域中配置了E和A的地址前缀。当主机Ha要与主机Hc通信时,Ha发给Hc的数据包可以经过路径Ha -> F1 -> C1 -> E -> B -> G -> Hc到达,但是反向数据包(主机Hc要与主机Ha通信)的路径却是Hc -> G -> B -> A -> B -> E -> C1 -> F1 -> Ha。正向路径有6跳,反向路径有8跳,反向路径中B出现了两次。

问题分析:在反向数据传送中,从B上行到A,在A中进行封装后,再从A下行到B,是因为B中没有C1到E的短接地址映射表,而A中有,所以数据包只能从B上行到A,在A中封装后,才能下行经B去E。

解决方案:我们增加一条规则,不仅在间接短接节点域A中保存C1的地址前缀与E地址前缀的映射表,还要求在直接短接节点域E与间接短接节点域A之间的所有途径的结点域都保存这个映射表项,于是在B中保存映射表项。这样,数据包就会被第一个遇到的匹配映射表项进行封装,又因为数据包的信宿是E,故不会进行重复包装,进而解决了重复路径。

伪代码实现:

void repeat_tunnel(Node *A) {
	A = A->chlidren[0];
	A->shorttable[0].nextip = "00000";
	A->len_shorttable = 1;
}

运行结果:如图3所示。

                                                                                    图 3 重复路径运行结果

四、循环路径

问题描述:循环路径问题就是在短接信道上数据传送一直进行死循环,数据送不到目的地。以图1中的拓扑图为例,我们首先建立内部短接信道(A—H)并在直接短接结点域A、H中配置相应的地址前缀。当主机Hb要向节点域M通信时,由于短接路径优先原则,Hb发给M的数据包的路径为Hb -> L -> H -> A -> D -> H -> A -> D -> H -> A……将一直循环下去,进而使数据送不到目的地。

问题分析:从Hb经过节点域L到节点域H时,传送数据的过程都是正常的,到了H后,由于H为直接短接节点域,故数据将会传送到直接短接节点域A,然后经过结点域D,又一次到达H,故又一次进行短接通信,如此以来,将会永远重复下去。

解决方案:添加一条规则,在数据传送时,依然优先判断短接表,然后把信宿地址的前缀与当前结点的前缀和短接表的前缀分别作比较,判断两者前缀的重合率大小,若当前结点的重合率大于短接表中前缀重合率,则放弃短接信道,而选择其他信道;若当前结点的重合率小于或等于短接表中前缀重合率,则选择短接信道进行传送。

伪代码实现:

void circle_path(Node *user) {
	printf("%s->", user->name);
	user->father->data = user->data;
	user = user->father;
	while (strcmp(user->ip, user->data->des_ip) != 0) {
	int skip = 0;
	printf("%s->", user->name);
	if (user->len_shorttable != 0) {
	for (int i = 0; i < user->len_shorttable; i++) {
		int count = 0;
		int ret = 0;
		for (int j = 0; j < strlen(user->shorttable[i].exIp); j++) {
			if (*(user->data->des_ip + j) != *(user->shorttable[i].exIp + j)) {
				count = 0;
				break;
			}
			count = 1;
			}
		if ((ret == 0) || (strlen(user->shorttable[i].exIp) > strlen(user->ip) && ret == 1)) {
			if (count == 1 && user->shorttable[i].nextip == NULL) {
				skip = 1;
				user->data->in_desip = NULL;
				user->out_node->data = user->data;
				user = user->out_node;
				break;
				}
			if (count == 1 && user->shorttable[i].nextip != NULL) {
				user->data->in_desip = user->shorttable[i].nextip;
					}
				}
			}
		}
		if (skip == 1) {
			continue;
		}
……
}

运行结果:如图4-5所示。

                                                                            图 4 循环路径失败运行结果图

                                                                               图 5 循环路径成功运行结果图

五、完整代码

由于代码太长,不宜放在博客文档中,如有需要,请到作者主页下载https://download.csdn.net/download/lph188/10802453

参考书籍:层次交换网络体系结构(钱华林)如需下载电子版,请到作者主页下载https://download.csdn.net/download/lph188/10806315

猜你喜欢

转载自blog.csdn.net/lph188/article/details/84375561