【发布时间】:2016-09-19 01:55:53
【问题描述】:
我正在尝试使用 unix 套接字和 c++ 实现距离矢量路由。
我正在运行多个客户端程序实例(每个实例都有一个虚拟网络接口的 IP,因此它可以绑定到该 IP)。每个客户端都在尝试模拟路由器。到目前为止,它是这样做的->
part-1) 从文件加载初始路由表。 [只是关于它的邻居的信息。] part-2) 将它的路由表信息发送给邻居。
我在第 2 部分的当前实施中遇到了问题。
//数据结构
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include<thread>
#include<bits/stdc++.h>
#include <chrono>
using namespace std;
#define MAX 10000
#define MAXCHAR 2048
int sockfd;
int bind_flag;
int sent_bytes;
int bytes_received;
char buffer[MAXCHAR];
socklen_t addrlen;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
struct sockaddr_in dummy;
string ip1, ip2;
int cost;
struct routing_table_entry{
string next_hop;
int cost;
routing_table_entry(){
}
routing_table_entry(string next_hop, int cost){
this->next_hop=next_hop;
this->cost=cost;
}
};
map<string, routing_table_entry> routing_table;
路由表发送器功能
void send_table_to_neighbor(){
it = routing_table.begin();
ostringstream message;
while(it!= routing_table.end()){
if((it->first).compare((it->second).next_hop) ==0){ //neighbour check
cout<<"Sending table to: "<<it->first<<endl;
inet_pton(AF_INET,(it->first).c_str(),&server_address.sin_addr);
cout<<"Neighbour IP: "<<it->first<<endl;
nest = routing_table.begin();
while(nest != routing_table.end()){
message.clear();
message.str("");
// destination next hop cost
message<< (nest->first)<<" "<<myIP<<" "<<(nest->second).cost<<" "; //destination
string message_string = message.str();
strcpy((char*)buffer_S, message_string.c_str());
cout<<"Message string: "<<message_string<<endl;
printf("Sending to: [%s:%hu]: %s\n", inet_ntoa(server_address.sin_addr), ntohs(server_address.sin_port), buffer_S);
sent_bytes=sendto(sockfd, buffer_S, MAXCHAR, 0, (struct sockaddr*) &server_address, sizeof(sockaddr_in));
int random = rand() % 2 + 1;
// std::this_thread::sleep_for (std::chrono::seconds(random));
nest++;
}
string terminate = "shutdown";
strcpy((char*)buffer_S, terminate.c_str());
printf("Sending to: [%s:%hu]: %s\n", inet_ntoa(server_address.sin_addr), ntohs(server_address.sin_port), buffer_S);
sent_bytes=sendto(sockfd, buffer_S, MAXCHAR, 0, (struct sockaddr*) &server_address, sizeof(sockaddr_in));
// cout<<buffer <<endl;
}
int random = rand() % 3 + 2;
// std::this_thread::sleep_for (std::chrono::seconds(random));
it++;
}
return;
}
接收表格并更新表格的函数。
void update_routing_table(){
cout<<"My IP: "<<myIP<<endl;
while(true){
addrlen= sizeof(dummy);
cout<<"Started reading:...."<<endl;
bytes_received = recvfrom(sockfd, buffer_R, MAXCHAR , 0, (struct sockaddr*) &dummy, &addrlen);
//bytes_received = recvfrom(sockfd, buffer_R, MAXCHAR , 0, (struct sockaddr*) &dummy, &addrlen);
cout<<"Stop reading:...."<<endl;
string data(buffer_R);
printf("Received from: [%s:%hu]: %s\n", inet_ntoa(dummy.sin_addr), ntohs(dummy.sin_port), buffer_R);
if(! data.compare("shutdown")){
cout<<"----------------------"<<endl;
printf("Received SHUTDOWN from: [%s:%hu]: %s\n", inet_ntoa(dummy.sin_addr), ntohs(dummy.sin_port), buffer_R);
cout<<"----------------------"<<endl;
_count++;
}
if(_count==3)
break;
istringstream data_buff(data);
string dest, next_hop;
data_buff>>dest>>next_hop>>cost;
cout<<"Receiving: "<<dest<<" "<<next_hop<<" "<<cost<<endl;
it= routing_table.find(dest);
if(it != routing_table.end()){
//update the table
temp = routing_table.find(next_hop); //next_hop is my neigbour
if((temp->second).cost + cost < (it->second).cost ){ // A-B-X , (A->B) + (B->X) < (A->X)
//it->second = routing_table_entry(next_hop, cost);
routing_table[it->first]=routing_table_entry(next_hop, (temp->second).cost + cost);
cout<<"Inside."<<endl;
cout<<dest<<" "<<next_hop<<" "<<cost<<endl;
cout<<it->first<<" "<<(it->second).next_hop<<" "<<(it->second).cost<<endl;
cout<<"DEBUG"<<endl;
print_routing_table();
// send_table_to_neighbor();
}
}
//int random = rand() %2 +1;
// std::this_thread::sleep_for (std::chrono::seconds(random));
}
return;
}
主函数,
int main(int argc, char *argv[]){
if(argc != 2){
printf("%s <ip address>\n", argv[0]);
exit(1);
}
//FILE* topo=freopen("topo.txt", "r", stdin);
ifstream file("topo.txt");
myIP=string(argv[1]);
string hold;
while(getline(file, hold)){
istringstream input(hold);
input>>ip1>>ip2>>cost;
if(!myIP.compare(ip1))
routing_table[ip2]=routing_table_entry(ip2, cost); // destination ip2, next hop ip2
else if(!myIP.compare(ip2))
routing_table[ip1]=routing_table_entry(ip1, cost); //destination ip1, next hop ip1
else{
it= routing_table.find(ip1);
if(it == routing_table.end())
routing_table[ip1]= routing_table_entry("-", MAX);
it= routing_table.find(ip2);
if(it == routing_table.end())
routing_table[ip2]= routing_table_entry("-", MAX);
}
}
file.close();
print_routing_table();
it= routing_table.begin();
server_address.sin_family = AF_INET;
server_address.sin_port = htons(4747);
client_address.sin_family = AF_INET;
client_address.sin_port = htons(4747);
//client_address.sin_addr.s_addr = inet_addr(argv[1]);
inet_pton(AF_INET,argv[1],&client_address.sin_addr);
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
cout<< "Socket value "<<sockfd <<endl;
bind_flag = bind(sockfd, (struct sockaddr*) &client_address, sizeof(sockaddr_in));
if(bind_flag==0)
printf("successful bind\n");
send_table_to_neighbor();
update_routing_table();
cout<<"<<My IP is: "<<myIP<<endl;
print_routing_table();
close(sockfd);
return 0;
}
现在,从主函数开始,我先调用 i) send_table_to_neighbor(),然后 ii) update_routing_table() [每个路由器程序都会这样做]
当我运行所有路由器程序时,并非所有程序都接收到所有发送的数据。某些发送的数据从未收到。 [这是不使用任何线程]
我尝试过使用线程(从 cmets 可见),但在这种情况下,路由器不会按顺序接收发送的消息,因此“关闭”消息在其他消息之前到达并且它们停止运行 [关闭消息:将总路由表发送给邻居后,我将向该邻居发送“关闭”消息,以便它可以停止期待来自该路由器的消息。我正在检查是否所有邻居都将它们关闭,只有这样路由器才会停止执行“update_routing_table”]
请建议我如何将消息从多个路由器传递到其他数量的路由器,以使每个路由器都接收所有消息。
Topo.txt:http://codepad.org/Z0cDGHvX 虚拟网络接口的设置文件:http://codepad.org/MDoJzpTx
【问题讨论】:
标签: c++ multithreading sockets unix networking