Skip to content

Commit

Permalink
dsdv
Browse files Browse the repository at this point in the history
  • Loading branch information
Frank authored and Frank committed Apr 29, 2014
0 parents commit af86e1f
Show file tree
Hide file tree
Showing 18 changed files with 796 additions and 0 deletions.
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# NOTE: Feel free to change the makefile to suit your own need.

# compile and link flags
CC=g++

all:
g++ -std=c++0x -pthread dsdv.cpp rip.cpp socket.cpp -o dsdv


clean:
rm -f *~ *.o dsdv
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@


文件构成:
本次lab主要由5个文件构成
socket.h & socket.cpp用来提供udp socket方面的接口和实现,具体内容可以参考socket.h

rip.h & rip.cpp用来提供路由算法的接口和实现,主要包含两个struct和6个函数接口

struct RouterTab:用来保存路由表中每一行的数据,其中seqNum表示重点的seqNum
struct Host:用来表示主机,包括主机的名称,seqNum和路由表的行数

void ripInit(string filename, map<string, struct RouterTab> &table, map<int, string> &adjTab, struct Host &host)
用来初始化路由器,从filename中读入表项并将其保存到table中,将端口号和名称的映射保存在adjTab中,将host信息保存到host中
void ripSend(string &content, map<string, struct RouterTab> &table, struct Host &host)
用来住准备发送内容,将主机信息和路由表转换成string保存到content中
void ripUpdate(struct Host from, map<string, struct RouterTab> &srcTab, map<string, struct RouterTab> &adjTable, map<string, struct RouterTab> &routeTable, struct Host &host)
当收到邻节点from的路由表srcTab是,根据主机保存的信息更新
void ripRefresh(map<string, struct RouterTab> &bufferdAdj, map<string, struct RouterTab> &newAdj, map<string, struct RouterTab> &table, struct Host &host)
根据重新从磁盘读入的newAdj和之前保存的bufferAdj来更新host的信息
void ripReceive(string content, map<string, struct RouterTab> &srcTab, struct Host &from);
将收到邻节点的content信息转换成srcTab的路由表和from的路由器信息
void ripPrintTable(map<string, struct RouterTab> &table, int &printNum, struct Host &host)
打印主机信息


dsdv.cpp
模拟路由器本身,采用双线程的方式,一个线程用来监听udp端口,接受并且更新路由表。另一个线程用来定时刷新路由表并且发送。详细参见dsdv.cpp

路由表查找及更新的算法
采用了dsdv的基本思路,通过seqNum来表示路由的最新状态。路径中的seqNum代表末节点的seqNum,其中如果seqNum是奇数,表示路由器正处在中间状态,他不能被更新,也不能更新其他路由器
1.从硬盘刷新路由表:从硬盘读取新数据,比对路由器缓存的旧表(adjBuf),如果有变动,将自己的seqNum ++,同时将所有的到邻节点的路全部强制刷新成直接链接。并且更新路由表中所有通过邻节点的路径的cost。
2.从邻节点更新路由表:首先存在4中情况:1.from seqNum 为偶数,host 为偶数;2.from 偶数,host奇数;3.from 奇数,host 奇数;4.from 奇数, host 偶数;
对于1.from为中间状态,忽略
2.host处于中间状态,忽略
3.表示from和host正好是更新的边的两端点,更新到对应路径的seqNum,并且自身的seqNum ++
4.又可以分为两种子情况,如果from的路由表中到自己的路线的seqNum为奇数,更行他的seqNum,此时中间状态完全结束,否则进行正常更新步骤
由于硬盘刷新策略的设计是全部换成直连,所以当host路由表中发现from的seqNum大于路由表中保存的信息时,从buffer的邻节点表中更新所有到邻节点的路径。并且对路由表的路径也进行重新计算
如果发现相等,对于所有路径进行更新:如果from中终点的seqNum较大,强制更新。否则重新计算路径的cost,以及判断是否改变路由路线从而获取最优值

对于这个算法,只要有路线变化,他们的影响就会从变化的两个端点扩散出去,最差的情况可能就是整张路由表全部直间连接(相当与重建),然后逐步优化到最优,虽然效率一般,但是实现比较方便。




46 changes: 46 additions & 0 deletions README~
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
ID: 5110379042
Name: 付周望
E-mail: [email protected]

文件构成:
本次lab主要由5个文件构成
socket.h & socket.cpp用来提供udp socket方面的接口和实现,具体内容可以参考socket.h

rip.h & rip.cpp用来提供路由算法的接口和实现,主要包含两个struct和6个函数接口

struct RouterTab:用来保存路由表中每一行的数据,其中seqNum表示重点的seqNum
struct Host:用来表示主机,包括主机的名称,seqNum和路由表的行数

void ripInit(string filename, map<string, struct RouterTab> &table, map<int, string> &adjTab, struct Host &host)
用来初始化路由器,从filename中读入表项并将其保存到table中,将端口号和名称的映射保存在adjTab中,将host信息保存到host中
void ripSend(string &content, map<string, struct RouterTab> &table, struct Host &host)
用来住准备发送内容,将主机信息和路由表转换成string保存到content中
void ripUpdate(struct Host from, map<string, struct RouterTab> &srcTab, map<string, struct RouterTab> &adjTable, map<string, struct RouterTab> &routeTable, struct Host &host)
当收到邻节点from的路由表srcTab是,根据主机保存的信息更新
void ripRefresh(map<string, struct RouterTab> &bufferdAdj, map<string, struct RouterTab> &newAdj, map<string, struct RouterTab> &table, struct Host &host)
根据重新从磁盘读入的newAdj和之前保存的bufferAdj来更新host的信息
void ripReceive(string content, map<string, struct RouterTab> &srcTab, struct Host &from);
将收到邻节点的content信息转换成srcTab的路由表和from的路由器信息
void ripPrintTable(map<string, struct RouterTab> &table, int &printNum, struct Host &host)
打印主机信息


dsdv.cpp
模拟路由器本身,采用双线程的方式,一个线程用来监听udp端口,接受并且更新路由表。另一个线程用来定时刷新路由表并且发送。详细参见dsdv.cpp

路由表查找及更新的算法
采用了dsdv的基本思路,通过seqNum来表示路由的最新状态。路径中的seqNum代表末节点的seqNum,其中如果seqNum是奇数,表示路由器正处在中间状态,他不能被更新,也不能更新其他路由器
1.从硬盘刷新路由表:从硬盘读取新数据,比对路由器缓存的旧表(adjBuf),如果有变动,将自己的seqNum ++,同时将所有的到邻节点的路全部强制刷新成直接链接。并且更新路由表中所有通过邻节点的路径的cost。
2.从邻节点更新路由表:首先存在4中情况:1.from seqNum 为偶数,host 为偶数;2.from 偶数,host奇数;3.from 奇数,host 奇数;4.from 奇数, host 偶数;
对于1.from为中间状态,忽略
2.host处于中间状态,忽略
3.表示from和host正好是更新的边的两端点,更新到对应路径的seqNum,并且自身的seqNum ++
4.又可以分为两种子情况,如果from的路由表中到自己的路线的seqNum为奇数,更行他的seqNum,此时中间状态完全结束,否则进行正常更新步骤
由于硬盘刷新策略的设计是全部换成直连,所以当host路由表中发现from的seqNum大于路由表中保存的信息时,从buffer的邻节点表中更新所有到邻节点的路径。并且对路由表的路径也进行重新计算
如果发现相等,对于所有路径进行更新:如果from中终点的seqNum较大,强制更新。否则重新计算路径的cost,以及判断是否改变路由路线从而获取最优值

对于这个算法,只要有路线变化,他们的影响就会从变化的两个端点扩散出去,最差的情况可能就是整张路由表全部直间连接(相当与重建),然后逐步优化到最优,虽然效率一般,但是实现比较方便。




4 changes: 4 additions & 0 deletions a.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
3 a
b -2.0 3032
c 5.0 3033
d 1.0 3034
4 changes: 4 additions & 0 deletions a.dat~
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
3 a
b 2.0 3032
c 5.0 3033
d 1.0 3034
4 changes: 4 additions & 0 deletions b.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
3 b
a -2.0 3031
c 3.0 3033
d 2.0 3034
4 changes: 4 additions & 0 deletions b.dat~
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
3 b
a 2.0 3031
c 3.0 3033
d 2.0 3034
6 changes: 6 additions & 0 deletions c.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
5 c
b 3.0 3032
d 3.0 3034
a 5.0 3031
e 1.0 3035
f 5.0 3036
5 changes: 5 additions & 0 deletions d.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
4 d
c 3.0 3033
e 1.0 3035
a 1.0 3031
b 2.0 3032
Binary file added dsdv
Binary file not shown.
144 changes: 144 additions & 0 deletions dsdv.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#include "rip.h"
#include "socket.h"
#include <stdio.h>
#include <stdlib.h>
#include <thread>
#include <mutex>
#include <pthread.h>
#include <unistd.h>
#include <iostream>
#include <arpa/inet.h>
#include <sys/socket.h>

using namespace std;

mutex mtx;

//global variable

//store the table from disk temporarily
map<string, struct RouterTab> myTable;

//store adjacent nods map
map<string, struct RouterTab> adjBuf;

//store the route table
map<string, struct RouterTab> routerTable;

//store the map from port number to the name of router
map<int, string> portToName;

//store the host message
struct Host host;

//store the socket fd
int fd;

//store the print time
int printNum;


void* receive(void* ptr)
{
//cout<<"thread 1\n";

while(1)
{
string content;
int fromPort = socketReceive(fd, content);
//cout<<"receive from: "<<fromPort<<endl;
//cout<<"receive content: "<<content<<endl;
//cout<<"========================\n";

//update route table
string src = portToName.find(fromPort)->second;
Host srcRouter;
srcRouter.name = src;
map<string, struct RouterTab> srcTab;

//cout<<"========================\n";
//cout<<"receive from: "<<src<<endl;
//cout<<"receive content: "<<content<<endl;
//cout<<"========================\n";

ripReceive(content, srcTab, srcRouter);
mtx.lock();
ripUpdate(srcRouter, srcTab, adjBuf, routerTable, host);
mtx.unlock();

/*
string sentContent;
ripSend(sentContent, routerTable);
//cout<<sentContent;
if(fromPort != -1)
socketSend(fd, fromPort, sentContent);
*/
}

}

int main(int argc, char *argv[])
{
if(argc != 3)
{
printf("usage: %s <prot_number> <file_name>\n", argv[0]);
exit(-1);
}

int port = atoi(argv[1]);
if(port <= 0)
{
printf("error: invalid <port_number>\n");
exit(-1);
}

string filename = string(argv[2]);

try
{
//init

ripInit(filename, routerTable, portToName, host);
ripInit(filename, adjBuf, portToName, host);
cout<<"This is router "<<host.name<<" listening port "<<port<<endl;

fd = socketBind(port);
int fromPort = -1;

pthread_t child;
pthread_create(&child, NULL, receive, NULL);

while(1)
{
//refresh the table from data
Host temp;
myTable.clear();
mtx.lock();
ripInit(filename, myTable, portToName, temp);
ripRefresh(adjBuf, myTable, routerTable, host);
mtx.unlock();

//print table
ripPrintTable(routerTable, printNum, host);

//prepare to send
string sendContent;
ripSend(sendContent, routerTable, host);

//send router table to adjacent nodes
map<int, string>::iterator it = portToName.begin();
for(; it != portToName.end(); it ++)
{
socketSend(fd, it->first, sendContent);
}

sleep(1);
}
close(fd);
}
catch(int e)
{
cout<<"Oops! error code: "<<e<<endl;
}
return 0;
}
4 changes: 4 additions & 0 deletions e.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
3 e
d 1.0 3034
f 2.0 3036
c 1.0 3033
3 changes: 3 additions & 0 deletions f.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
2 f
e 2.0 3035
c 1.0 3033
1 change: 1 addition & 0 deletions make
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
g++ -std=c++0x -pthread dsdv.cpp rip.cpp socket.cpp -o dsdv
Loading

0 comments on commit af86e1f

Please sign in to comment.