IPV6路由算法时遇到一个处理IPV6地址的问题

zw24127 2008-10-31 12:34:15
使用的C++,想对一个IPV6地址(128位,采用冒号分16进制)字符串进行处理,变成一个int数组中(存放16进制),不知道有没有什么好的方法?欢迎大家讨论!
如:IPV6地址:2002:AD72::33b2 转换成int数组为:{0x2002,0xAD72,0x0000,0x0000,0x0000,0x0000,0x0000,0x33B2}
或者有没有什么对IPV6地址好的处理方法,路由查询是按前缀长度进行匹配的
...全文
365 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
zw24127 2008-11-30
  • 打赏
  • 举报
回复
//通过前缀长度找到该前缀长度在树中的位置下标
int findIndex(int t){
int i=0;
for(i=0;i<treeLen;i++){
if(tree[i].len==t){
return i;
}
}
return i;
}
//对IPV6地址进行转化,从一个字符串转化为一个整形数组,路由中的地址只取其前缀即可
int* convertToInt(char* address,int len){
int reLen=(int)((len-1)/16)+1;
int *re=new int[reLen];
char ad[40];
int firstM=0;
int mNum=0;//:的个数
int mm=-1;//::在字符串数组中的下标
bool b=false;//用于判断中:还是::
int i;
int length=strlen(address);
for(i=0;i<length;i++){//遍历字符串(IPV6地址)数组,确定mNum和mm的值
if(address[i]==':'){
if(b==true){
mm=i;
}
b=true;
mNum++;
}else{
b=false;
}
ad[i]=address[i];
}
ad[i]='\0';
if(mm!=-1){//有::即0地址压缩时,添加未输入的0
if(mm==(length-1)){
mNum--;
ad[mm]='\0';
}
if(mm==1){//::在开始位置
ad[0]='0';
int k=i;
for(;k>=mm;k--){
ad[k+1]=ad[k];
}
}
int j=2*(8-mNum)-1;
for(;i>=mm;i--){
ad[i+j]=ad[i];
}
for(i=0;i<j;i++){
if((i%2)==0){
ad[mm+i]='0';
}else{
ad[mm+i]=':';
}
}
}
length=strlen(ad);//添加0后的IPV6地址所占字符串的长度
char p[5];//IPV6地址采用冒号分16进制,每段最多4位
int pI=0;//p所用到的位数
int tempI=0;
int indexRe=0;
for(i=0;i<length;i++){
if(ad[i]==':'){
p[pI]='\0';
istringstream in(p);
in >> hex >>tempI;//16进制字符串转化成10进制
re[indexRe]=tempI;//转化成16进制
indexRe++;
if(indexRe==reLen){
break;
}
pI=0;
}else{
p[pI]=ad[i];
pI++;
}
}
p[pI]='\0';
istringstream in(p);
in >> hex >>tempI;//16进制字符串转化成10进制
re[indexRe]=tempI;//转化成16进制
return re;
}
//产生一个Marker
struct Marker* makeMarker(int len,int *a){
struct Marker *temp=new struct Marker();
temp->prefix=new int[(len-1)/16+1];
for(int i=0;i<((len-1)/16+1);i++){
temp->prefix[i]=a[i];
}
temp->next=NULL;
return temp;
}
//建立二分查找树
void build(int start,int end){
if(start<end){
int mid=(start+end)/2;
build(mid+1,end);//建立后面的树,即后面的marker
int temp=(mid+1+end)/2;
while(temp!=(mid+1)){//mid的marker是由它的右子树和它右子的往左一直到底所有marker在mid所在前缀长度的合集
checkNode(mid,temp);
temp=(temp+mid)/2;
}
checkNode(mid,temp);
build(start,mid-1);
}
}
//把temp结点加到mid的Marker表中去
void checkNode(int mid,int temp){
if(tree[temp].marker!=NULL){//temp的Marker加到mid的Marker表中去
struct Marker *m=tree[temp].marker;
struct Marker *mMid=tree[mid].marker;
while(m!=NULL){
mMid=tree[mid].marker;
if(mMid==NULL){
mMid=makeMarker(tree[mid].len,m->prefix);
tree[mid].marker=mMid;
}else{
while(mMid!=NULL){
if(isEquils(mMid->prefix,m->prefix,tree[mid].len)==true){
break;
}
mMid=mMid->next;
}
if(mMid==NULL){
mMid=makeMarker(tree[mid].len,m->prefix);
mMid->next=tree[mid].marker;
tree[mid].marker=mMid;
}
}
m=m->next;
}
}
for(int i=0;i<tree[temp].startLen;i++){
struct Node *m=&node[tree[temp].start[i]];
struct Marker *mMid=tree[mid].marker;
if(mMid==NULL){
mMid=makeMarker(tree[mid].len,m->prefix);
tree[mid].marker=mMid;
}else{
while(mMid!=NULL){
if(isEquils(mMid->prefix,m->prefix,tree[mid].len)==true){
break;
}
mMid=mMid->next;
}
if(mMid==NULL){
mMid=makeMarker(tree[mid].len,m->prefix);
mMid->next=tree[mid].marker;
tree[mid].marker=mMid;
}
}
}
}

//给定两个前缀长度在给定长度的时候判断是否相等
bool isEquils(int *a,int *b,int len){
int temp1=len/16;
int temp2=16-len%16;
int i;
for(i=0;i<temp1;i++){
if(a[i]!=b[i]){
return false;
}
}
if(i==temp1&&i!=0){
return true;
}
int a1=a[i]&((0xffff)<<temp2);
int a2=b[i]&((0xffff)<<temp2);
if(a1!=a2){
return false;
}
return true;
}
//依次进行查询
int query(int *qAddress,int start,int end){
int re=-1,i;
if(start>=end){//叶子结点无marker表
for(i=0;i<tree[start].startLen;i++){
if(isEquils(node[tree[start].start[i]].prefix,qAddress,tree[start].len)==true){
re=tree[start].start[i];//记住在node中的下标
break;
}
}
}else{
int mid=(start+end)/2;
for(i=0;i<tree[mid].startLen;i++){
if(isEquils(node[tree[mid].start[i]].prefix,qAddress,tree[mid].len)==true){
re=tree[mid].start[i];
break;
}
}
struct Marker *mk=tree[mid].marker;
while(mk!=NULL){
if(isEquils(mk->prefix,qAddress,tree[mid].len)==true){//marker表中前缀相同
break;
}
mk=mk->next;
}
int reB=-1;
if(mk!=NULL){//marker表中前缀相同,去右子查查看
reB=query(qAddress,mid+1,end);
}
if(reB==re){//即都为-1,那么只能在左子树中查找
re=query(qAddress,start,mid-1);
}else{
re=(reB==-1) ? re:reB;
}
}
return re;
}
//输出树,检查树是否构造出来时用的
void outTree(){
cout<<"----------------------------------------------------------"<<endl;
for(int i=0;i<treeLen;i++){
cout<<"tree "<<i<<"\t"<<endl;
cout<<"len="<<tree[i].len<<"\t startLen="<<tree[i].startLen<<endl;
for(int j=0;j<tree[i].startLen;j++){cout<<tree[i].start[j]<<"\t如下:";
// for(int k=0;k<(tree[i].len-1)/16+1;k++){
// cout<<node[tree[i].start[j]].prefix[k]<<"\t";
// }
cout<<node[tree[i].start[j]].nextHop<<endl;
}
cout<<endl;

cout<<"marker如下:"<<endl;
if(tree[i].marker==NULL){
cout<<"NO";
}else{
struct Marker *m=tree[i].marker;
while(m!=NULL){
for(int k=0;k<(tree[i].len-1)/16+1;k++){
cout<<m->prefix[k]<<"\t";
}
cout<<endl;
m=m->next;
}
}
cout<<endl;}
cout<<"----------------------------------------------------------"<<endl;
}

void output(){
// outTree();
int s;
for(int i=0;i<m;i++){
s=query(convertToInt((char*)queryIPAddress[i].c_str(),128),0,treeLen-1);
cout<<queryIPAddress[i]<<" ";
if(s>=0){
cout<<node[s].nextHop;
}else{
cout<<"No Route";
}
cout<<endl;
}
}
};
void main(){
//使用课件上给定的数据测试通过
RouterQuery rq=RouterQuery();
rq.start();
}
zw24127 2008-11-30
  • 打赏
  • 举报
回复
已解决,贴个我的算法:
------------------------------------------
#include<iostream>
#include<cstring>
#include<string>
#include<sstream>
#include<fstream>
//auth challenge email:yongzwl@qq.com
using namespace std;
//二分查找树中,每个要判断结点的Marker数据结构
struct Marker{
int *prefix;//存放IPV6地址的前缀
struct Marker *next;
};
//路由中每一条路由信息的数据结构
struct Node{
int *prefix;//IPV6地址的前缀
char nextHop;//路由记录中的下一跳
};
//二分查找树的数据结构
struct BTree{
int len;//前缀长度
int *start;//在长度在排序好的路由信息数组中的开始下标
int startLen;//前缀长度为len的IP地址的个数
struct Marker *marker;
};
class RouterQuery{
private:

int n,m,treeLen;//n路由的表总共的个数,m要查询的IPV6地址的个数,treeLen是tree的长度即无重复前缀长度的个数
string *queryIPAddress;//记录要查询的IPV6地址
struct Node *node;//记录所有输入的路由结点
struct BTree *tree;//二分查找树

public:
//构造函数
RouterQuery(){
n=0;
m=0;
}
//析构函数,释放指针空间
~RouterQuery(){
// delete queryIPAddress;
// delete node;
// delete tree;
}
//入口
void start(){
incc();
// input();//输入
build(0,treeLen-1);//建树
output();//输出
}
//data.txt
void incc(){
ifstream in("data.txt");
char ch;
in>>n;
//cout<<n;
in.get(ch);
//cout<<ch;
node=new struct Node[n];
//前缀长度数组
int *len=new int[n];
//输入的一个IPV6地址
char *address=new char[40];
int i,j;
//用来存储每个前缀长度共有多少个IPV6地址
int *temp=new int[129];
for(i=0;i<129;i++){
temp[i]=0;
}
for(i=0;i<n;i++){
m=0;
in.get(ch);
//cout<<ch;
while((*(address+m)=ch)!='/'){
in.get(ch);
//cout<<ch;
m++;
}
in>>len[i];
//cout<<len[i];
in.get(ch);
//cout<<ch;
in.get(ch);
//cout<<ch;
node[i].nextHop=ch;
*(address+m)='\0';
temp[len[i]]++;
node[i].prefix=convertToInt(address,len[i]);
in.get(ch);
//cout<<ch;
// len[i]=inLen[i];temp[len[i]]++;
// node[i].nextHop=inNextHop[i];
// node[i].prefix=convertToInt(inAddress[i],len[i]);
}
in>>m;
//cout<<m;
in.get(ch);
//cout<<ch;
queryIPAddress=new string[m];
char ttt[40];
for(i=0;i<m;i++){
j=0;
in.get(ch);
//cout<<ch;
while(ch!='\n'){
ttt[j]=ch;
j++;
in.get(ch);
//cout<<ch;
}
ttt[j]='\0';
queryIPAddress[i]=ttt;
// queryIPAddress[i]=qAdd[i];
// cin>>queryIPAddress[i];
}
//前缀长度的个数
int index=0;
//无重复的前缀长度
int *temp1=new int[129];
for(i=0;i<129;i++){
if(temp[i]!=0){
temp1[index]=i;
index++;
}
}
tree=new struct BTree[index];
treeLen=index;
for(i=0;i<index;i++){
tree[i].len=temp1[i];
tree[i].start=new int[temp[temp1[i]]];
tree[i].startLen=0;
tree[i].marker=NULL;
}
for(i=0;i<n;i++){
index=findIndex(len[i]);
tree[index].start[tree[index].startLen]=i;
tree[index].startLen++;
}
delete(address);
delete(temp);
delete(temp1);
delete(len);
}

//protected:
//获取输入数据
void input(){
// char *inAddress[]={"2001:250:f007:31::","2001:250:f007:32::","2001:250:f007::/48","2001:250:f007:31:25::","2001:250:f007:31:ff25::"};
// int inLen[]={64,64,48,72,72};
// char inNextHop[]={'A','B','C','D','E'};
// string qAdd[]={"2001:250:f007:31::200","2001:250:f007:ffff::200","2001:250:fe07::200"};
cin>>n;
node=new struct Node[n];
//前缀长度数组
int *len=new int[n];
//输入的一个IPV6地址
char *address=new char[40];
int i;
//用来存储每个前缀长度共有多少个IPV6地址
int *temp=new int[129];
for(i=0;i<129;i++){
temp[i]=0;
}
for(i=0;i<n;i++){
m=0;
while((*(address+m)=getchar())!='/'){
m++;
}
cin>>len[i];
getchar();
cin>>node[i].nextHop;
*(address+m)='\0';
temp[len[i]]++;
node[i].prefix=convertToInt(address,len[i]);
// len[i]=inLen[i];temp[len[i]]++;
// node[i].nextHop=inNextHop[i];
// node[i].prefix=convertToInt(inAddress[i],len[i]);
}
cin>>m;
queryIPAddress=new string[m];
for(i=0;i<m;i++){
// queryIPAddress[i]=qAdd[i];
cin>>queryIPAddress[i];
}
//前缀长度的个数
int index=0;
//无重复的前缀长度
int *temp1=new int[129];
for(i=0;i<129;i++){
if(temp[i]!=0){
temp1[index]=i;
index++;
}
}
tree=new struct BTree[index];
treeLen=index;
for(i=0;i<index;i++){
tree[i].len=temp1[i];
tree[i].start=new int[temp[temp1[i]]];
tree[i].startLen=0;
tree[i].marker=NULL;
}
for(i=0;i<n;i++){
index=findIndex(len[i]);
tree[index].start[tree[index].startLen]=i;
tree[index].startLen++;
}
delete address;
delete temp;
delete temp1;
delete len;
}
meng_jian 2008-11-26
  • 打赏
  • 举报
回复
关注!!
oo 2008-11-08
  • 打赏
  • 举报
回复
up

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧