【计算机网络】—— IP协议及动态路由算法(上)https://developer.aliyun.com/article/1507505?spm=a2c6h.13148508.setting.49.1b484f0eD2AqhJ
3、IP编址计算
3.1子网划分
将172.16.64.0/26划分为4个等长子网。
运行结果:
代码:
#include<iostream> #include<algorithm> #include<string.h> using namespace std; int b[40],index,ip[4]; void binary(int d) { int temp[8]= {0},i=0; int x=0; while(d>0) { int n=d%2; d=d/2; temp[i++]=n; x++; } while(x<8) { temp[i++]=0; x++; } for(int i=7; i>=0; i--) { b[index++]=temp[i]; } return; } int bin_dec(int x,int n) { if(n==0) { return 1; } return x*bin_dec(x,n-1); } void print(int pos,int num) { int count=0; if(pos==num) { for(int i=0; i<32; i++) { printf("%d ",b[i]); count++; if(count%8==0)printf(" "); } for(int i=0; i<8; i++) { if(b[i]==1) { ip[0]+=bin_dec(2,7-i); } } for(int i=8; i<16; i++) { if(b[i]==1) { ip[1]+=bin_dec(2,15-i); } } for(int i=16; i<24; i++) { if(b[i]==1) { ip[2]+=bin_dec(2,23-i); } } for(int i=24; i<32; i++) { if(b[i]==1) { ip[3]+=bin_dec(2,31-i); } } printf("对应十进制IP:%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); printf("/%d\n",num); memset(ip,0,sizeof(ip)); return; } b[pos]=1; print(pos+1,num); b[pos]=0; print(pos+1,num); } int main() { int d1=0,d2=0,d3=0,d4=0,prefix,bp[40]= {0},ips,ip_num=0; printf("请输入IP:"); scanf("%d.%d.%d.%d",&d1,&d2,&d3,&d4); printf("请输入前缀:"); scanf("%d",&prefix); printf("请输入划分子网的个数:"); scanf("%d",&ips); if(ips%2==0) { while(ips>1) { ips/=2; ip_num++; } } else { while(ips>0) { ips/=2; ip_num++; } } for(int i=0; i<prefix; i++) { bp[i]=1; } binary(d1); binary(d2); binary(d3); binary(d4); printf("计算过程:\n"); printf(" IP地址 :"); int count=0; for(int i=0; i<index; i++) { printf("%d ",b[i]); count++; if(count%8==0)printf(" "); } printf("\n"); printf("网络掩码:"); for(int i=0; i<32; i++) { printf("%d ",bp[i]); count++; if(count%8==0)printf(" "); } for(int i=0; i<32; i++) { b[i]=b[i]&bp[i]; } printf("\n"); printf("网络地址:"); for(int i=0; i<32; i++) { printf("%d ",b[i]); count++; if(count%8==0)printf(" "); } printf("\n\n"); printf("划分为2的%d次方个等长网络\n",ip_num); print(prefix,prefix+ip_num); return 0; }
3.2确定网络号(子网地址)
试确定172.115.116.117/21的子网地址。
因为/21,所以得出子网掩码为:255.255.248.0,通过与运算得出结果如图:
代码截图以及运行结果:
3.3路由总结
确定172.112.0.0/22、172.116.0.0/22、172.120.0.0/22这三个子网的路由总结。
方法一(C语言)运行结果:
代码:
#include<iostream> #include<algorithm> #include<string.h> using namespace std; int n; typedef struct ip_s { int d[4]; int ip[4],b[32]; } ip_s; ip_s ips[10]; ip_s binary(ip_s ip) { int temp[8]= {0},index=0,q=0; int x=0; for(int i=0; i<4; i++) { x=0; q=0; while(ip.d[i]>0) { int n=ip.d[i]%2; ip.d[i]=ip.d[i]/2; temp[q]=n; q++; x++; } while(x<8) { temp[q]=0; q++; x++; } for(q=7; q>=0; q--) { ip.b[index]=temp[q]; index++; } } return ip; } int bin_dec(int x,int n) { if(n==0) { return 1; } return x*bin_dec(x,n-1); } void print(int *ans) { int ip[32]; memset(ip,0,sizeof(ip)); for(int i=0; i<8; i++) { if(ans[i]==1) { ip[0]+=bin_dec(2,7-i); } } for(int i=8; i<16; i++) { if(ans[i]==1) { ip[1]+=bin_dec(2,15-i); } } for(int i=16; i<24; i++) { if(ans[i]==1) { ip[2]+=bin_dec(2,23-i); } } for(int i=24; i<32; i++) { if(ans[i]==1) { ip[3]+=bin_dec(2,31-i); } } printf("对应十进制IP:%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); return; } int main() { int prefix,ans[32],count=0; printf("请输入子网数量:"); scanf("%d",&n); printf("输入子网:\n"); for(int i=0; i<n; i++) { scanf("%d.%d.%d.%d",&ips[i].d[0],&ips[i].d[1],&ips[i].d[2],&ips[i].d[3]); ips[i]=binary(ips[i]); } for(int i=0; i<32; i++) { ans[i]=i; } for(int i=0; i<n; i++) { for(int j=0; j<32; j++) { ans[j]=ans[j]&ips[i].b[j]; } } for(int i=0; i<32; i++) { printf("%d ",ans[i]); count++; if(count%8==0)printf(" "); if(ans[i]!=0) { prefix=i; } } print(ans); printf("/%d",prefix+1); return 0; }
方法二(python语言)运行结果:
代码截图:
汇总后的地址空间为10101100 01110000 00000000 00000000,计算得到最后的路由总结为172.112.0.0/12。和方法一算出来的一样。
4、DHCP协议分析
4.1分析
要抓取到DHCP包,先要保证有可用的DHCP服务器,然后将主机IP地址获取方式设置为自动获取。我的主机在抓包之前已经联网,需要先断开主机的网络连接,然后再连接网络。在cmd下使用命令ipconfig来完成网络断开与连接的过程:
ipconfig /release :断开当前的网络连接,主机IP变为0.0.0.0,主机与网络断开,不能访问网络。
断开当前的网络连接
ipconfig /renew :更新适配器信息,请求连接网络,这条命令结束之后,主机会获得一个可用的IP,再次接入网络。
请求连接网络
4.2 DHCP协议抓包分析
捕捉到的报文通过bootp过滤,结果如下:
DHCP协议抓包截图
4.2.1 DHCP Discover包
Client端使用IP地址0.0.0.0发送了一个广播包,可以看到此时的目的IP为255.255.255.255。Client想通过这个数据包发现可以给它提供服务的DHCP服务器。从下图可以看出,DHCP属于应用层协议,它在传输层使用UDP协议,目的端口是67。
DHCP Discover包
4.2.2 DHCP Offer包
当DHCP服务器收到一条DHCP Discover数据包时,用一个DHCP Offerr包给予客户端响应。
DHCP Offer包
4.2.3 DHCP Request包
当Client收到了DHCP Offer包以后(如果有多个可用的DHCP服务器,那么可能会收到多个DHCP Offer包),确认有可以和它交互的DHCP服务器存在,于是Client发送Request数据包,请求分配IP。此时的源IP和目的IP依然是0.0.0.0和255.255.255.255。
DHCP Request包
4.2.4 DHCP ACK包
服务器用DHCP ACK包对DHCP请求进行响应。
DHCP ACK包
5、DV路由算法编程与测试;
路由路径拓扑图:
路由器数量及边数:7 7
边的开销:
1 2 8
2 3 8
3 7 8
1 4 6
4 5 6
5 6 6
6 7 6
代码截图:
#include<iostream> #include<algorithm> #define MAX 0x3f #define N 999 using namespace std; int nodenum,edgenum,original,destination; typedef struct Edge { int u,v; int cost; } Edge; Edge edge[N]; int dis[N],pre[N]; void Bellman_Ford() { for (int i=1; i<=nodenum; i++) { dis[i]=(i==original?0:MAX); } for (int i=1; i<=nodenum-1; i++) { for(int j=1; j<=edgenum; j++) { if(dis[edge[j].v]>dis[edge[j].u]+edge[j].cost) { dis[edge[j].v]=dis[edge[j].u]+edge[j].cost; pre[edge[j].v]=edge[j].u; } } } } void path_out(int p) { if(pre[p]!=p) { path_out(pre[p]); printf("-->",p); } printf("R%d",p); } int main() { printf("请输入路由器的数量以及边数:"); scanf("%d %d",&nodenum,&edgenum); printf("请输入边的开销:\n") ; for(int i=1; i<=edgenum; i++) scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].cost); printf("请输入源路由器以及目的路由器的编号:"); scanf("%d %d",&original,&destination); pre[original]=original; Bellman_Ford(); printf("DC的路径为:"); path_out(destination); return 0; }
DV路由算法
运行结果:
运行截图
6、LS路由算法编程与测试
路由路径拓扑图:
路由数及边数:7 8
边的开销:
1 2 8
2 3 8
3 7 8
1 4 6
4 5 6
5 6 6
6 7 6
5 3 2
代码截图:
#include<iostream> #include<algorithm> #include<string.h> #define N 999 using namespace std; int map[N][N],dist[N],book[N],path[N],n,m,original,destination; void dijkstra() { memset(dist,127,sizeof(dist)); dist[1]=0; memset(path,0,sizeof(path)); for(int i=1; i<=n; i++) { int x=0; for(int j=1; j<=n; j++) { if(!book[j] && ( x==0 || dist[j] < dist[x])) { x=j; } } book[x]=1; for(int j=1; j<=n; j++) { if(dist[j]>dist[x]+map[x][j]) { dist[j]=dist[x]+map[x][j]; path[j]=x; } } } } void path_out(int p) { if(path[p]!=0) { path_out(path[p]); printf("-->",p); } printf("R%d",p); } int main() { printf("请输入路由器的数量以及边数:"); scanf("%d %d",&n,&m); memset(map,127,sizeof(map)); printf("请输入边的开销:\n"); int a,b,z; for(int i=0; i<m; i++) { scanf("%d %d %d",&a,&b,&z); map[a][b]=min(map[a][b],z); } dijkstra(); printf("请输入源路由器以及目的路由器的编号:"); scanf("%d %d",&original,&destination); printf("开销为:%d\n",dist[destination]); printf("LS的路径为:"); path_out(destination); return 0; }
LS路由算法
运行结果:
运行截图
思考
1、如下图所示的Ping,返回的TTL是变化的,请问该网络为数据报(datagram)网络与虚电路(virtual-circuit)网络的那种可能性较大?TTL变化说明了什么?
根据图像所显示的信息,该网络为数据报(datagram)网络的可能性较大。因为在数据报网络中,TTL值的变化是正常的,而虚电路(virtual-circuit)网络中TTL值是不会变化的。
2、路由器根据分组的目的地址转发分组,基于路由协议/算法构建转发表,转发时检索转发表,每个分组独立选路,那么在支持等价路由的LS算法协议中(比如说OSPF),数据被分为很多个分组,很多个分组必然选择不同的路径到达目的地,但是Cost开销一致,并不代表时延一致,传输层在根据序号组包时,较大的时延会不会对TCP流量产生影响?影响的后果是什么?
等价路由是指在网络中使用多个路由路径将数据从源地址传输到目标地址,这些路径具有相同的成本和度量,并且可以同时用于传输数据。在支持等价路由的LS算法协议中,比如OSPF,数据被分为很多个分组,每个分组独立选路,因此可能会选择不同的路径到达目的地。虽然这些路径的成本开销一致,但并不代表时延一致。
当传输层根据序号组包时,较大的时延可能会对TCP流量产生影响。这是因为TCP协议是基于字节流的,它的数据传输是连续的,如果中间出现了较大的时延,可能会导致后续的数据包延迟发送,从而影响到数据的连续性和完整性。这种情况可能会导致接收方收到的数据出现丢包、重复包或者顺序错乱等问题,从而影响到TCP流量的正常传输。
具体的影响后果可能包括:重传机制触发,导致网络拥塞加剧;应用程序因为数据丢失或错误而出错;用户体验下降,例如视频卡顿、语音断续等。为了避免这些问题,网络设计者和管理员需要密切关注网络性能,确保数据能够沿着最优路径传输,同时采取措施减少时延和提高可靠性。