路由跟踪技术
时间:2022-04-22
本文章向大家介绍路由跟踪技术,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
用来确定路由器的IP地址,也就是在网络上到达特定主机所经过的计算机。
程序需要两个套接字:
1 一个用于接收ICMP封包的原始套接字sRaw
2 用于发送TTL不断增加UDP封包的套接字sSend。
实现代码如下:
void main()
{
char *szDestIp = "10.16.115.178"; // 210.181.18.12910.16.115.25 61.55.66.30
char recvBuf[1024] = { 0 };
// 创建用于接收ICMP封包的原始套节字,绑定到本地端口
SOCKET sRaw = ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
sockaddr_in in;
in.sin_family = AF_INET;
in.sin_port = 0;
in.sin_addr.S_un.S_addr = INADDR_ANY;
if(::bind(sRaw, (sockaddr*)&in, sizeof(in)) == SOCKET_ERROR)
{
printf(" bind() failed n");
return;
}
SetTimeout(sRaw, 5*1000);
// 创建用于发送UDP封包的套节字
SOCKET sSend = ::socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN destAddr;
destAddr.sin_family = AF_INET;
destAddr.sin_port = ::htons(22);
destAddr.sin_addr.S_un.S_addr = ::inet_addr(szDestIp);
int nTTL = 1;
int nRet;
ICMP_HDR *pICMPHdr;
int nTick;
SOCKADDR_IN recvAddr;
do
{
// 设置UDP封包的TTL值
SetTTL(sSend, nTTL);
nTick = ::GetTickCount();
// 发送这个UDP封包
nRet = ::sendto(sSend, "hello", 5, 0, (sockaddr*)&destAddr, sizeof(destAddr));
if(nRet == SOCKET_ERROR)
{
printf(" sendto() failed n");
break;
}
// 等待接收路由器返回的ICMP报文
int nLen = sizeof(recvAddr);
nRet = ::recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&recvAddr, &nLen);
if(nRet == SOCKET_ERROR)
{
if(::WSAGetLastError() == WSAETIMEDOUT)
{
printf(" time out n");
break;
}
else
{
printf(" recvfrom() failed n");
break;
}
}
// 解析接收到的ICMP数据
pICMPHdr = (ICMP_HDR*)&recvBuf[20]; // sizeof(IPHeader)
if(pICMPHdr->icmp_type != 11 && pICMPHdr->icmp_type != 3 && pICMPHdr->icmp_code != 3)
{
printf(" Unexpected Type: %d , code: %d n",
pICMPHdr->icmp_type, pICMPHdr->icmp_code);
}
else
{
char *szIP = ::inet_ntoa(recvAddr.sin_addr);
printf(" 第%d个路由器,IP地址:%s n", nTTL, szIP);
printf(" 用时:%d毫秒 n", ::GetTickCount() - nTick);
}
if(destAddr.sin_addr.S_un.S_addr == recvAddr.sin_addr.S_un.S_addr)
{
printf("目标可达 n");
break;
}
printf("//------------------------------------// n");
}while(nTTL++ < 20);
::closesocket(sRaw);
::closesocket(sSend);
}
- 为什么要学习编程?
- 楼盘价格数据采集与可视化分析
- Android LayoutInflater原理分析,带你一步步深入了解View(一)
- 深入理解Linux磁盘的奥秘
- Linux文件系统——全方位掌握
- TensorFlow和深度学习入门教程
- php+mysql实现分页代码
- 主成分分析降维(MNIST数据集)
- Android 使用dagger2进行依赖注入(基础篇)
- Html小知识总结
- 如何训练一个性能不错的深度神经网络
- 使用AndroidStudio编译NDK的方法及错误解决方案
- 计算机视觉 | Python OpenCV 3 使用背景减除进行目标检测
- linux(centos)搭建SVN服务器
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- LinkedList - 92. Reverse Linked List II
- LinkedList - 328. Odd Even Linked List
- LinkedList - 25. Reverse Nodes in k-Group
- LinkedList - 24. Swap Nodes in Pairs
- LinkedList - 141. Linked List Cycle
- LinkedList - 206. Reverse Linked List
- Array - 188. Best Time to Buy and Sell Stock IV
- Tree - 112. Path Sum
- 首个无tricks的情况下将ResNet-50提高到80%+!CMU开源MEAL V2
- Tree - 257. Binary Tree Paths
- Tree - 226. Invert Binary Tree
- Tree - 101. Symmetric Tree
- Tree - 100. Same Tree
- Tree - 102. Binary Tree Level Order Traversal
- Dynamic Programming - 91. Decode Ways