android接入traceroute in cpp by api
时间: 2024-06-09 11:05:44 浏览: 144
traceroute-for-android:适用于Android的traceroute
要在 Android 应用程序中使用 C++ 实现 traceroute,可以使用以下步骤:
1. 创建一个 C++ 类,该类将实现 traceroute 功能。这个类可以使用第三方库,如 libnet、libpcap 和 libtrace,来实现 traceroute。
2. 将 C++ 代码编译成共享库(.so 文件)。
3. 在你的 Android 项目中添加共享库文件。
4. 在 Java 代码中调用 C++ 的 traceroute 方法。
以下是一个简单的示例:
1. 创建一个名为 Traceroute 的 C++ 类,该类将实现 traceroute 功能。
```c++
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/ip_icmp.h>
#include <sys/types.h>
#include <time.h>
#define PACKETSIZE 64
class Traceroute {
public:
Traceroute(const char* hostname);
~Traceroute();
void run();
private:
const char* mHostname;
int mTtl;
int mSocket;
struct sockaddr_in mDestAddr;
char* mPacket;
struct timeval mTimeout;
fd_set mReadSet;
struct timeval mStartTime;
struct timeval mEndTime;
struct timeval mTimeDiff;
void sendPacket(int ttl);
int receivePacket(int ttl);
void printAddress(struct sockaddr_in addr);
};
```
2. 实现 Traceroute 类的构造函数和析构函数。
```c++
Traceroute::Traceroute(const char* hostname) {
mHostname = hostname;
mTtl = 1;
mSocket = -1;
mPacket = NULL;
memset(&mDestAddr, 0, sizeof(struct sockaddr_in));
memset(&mTimeout, 0, sizeof(struct timeval));
memset(&mReadSet, 0, sizeof(fd_set));
memset(&mStartTime, 0, sizeof(struct timeval));
memset(&mEndTime, 0, sizeof(struct timeval));
memset(&mTimeDiff, 0, sizeof(struct timeval));
}
Traceroute::~Traceroute() {
if (mSocket != -1) {
close(mSocket);
}
if (mPacket != NULL) {
free(mPacket);
}
}
```
3. 实现 Traceroute 类的 run 方法,该方法将实现 traceroute 功能。
```c++
void Traceroute::run() {
struct hostent* host;
struct timeval timeout;
int maxfd;
int ret;
int done = 0;
// resolve hostname
host = gethostbyname(mHostname);
if (host == NULL) {
printf("traceroute: unknown host %s\n", mHostname);
return;
}
// create socket
mSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (mSocket < 0) {
printf("traceroute: cannot create socket: %s\n", strerror(errno));
return;
}
// set socket options
setsockopt(mSocket, IPPROTO_IP, IP_TTL, &mTtl, sizeof(mTtl));
// set destination address
mDestAddr.sin_family = AF_INET;
mDestAddr.sin_port = 0;
memcpy(&mDestAddr.sin_addr, host->h_addr, host->h_length);
// allocate packet buffer
mPacket = (char*)malloc(PACKETSIZE);
if (mPacket == NULL) {
printf("traceroute: out of memory\n");
return;
}
// set timeout
timeout.tv_sec = 1;
timeout.tv_usec = 0;
// loop until done
while (!done) {
// send packet
sendPacket(mTtl);
// receive packet
ret = receivePacket(mTtl);
if (ret == 0) {
// reached destination
done = 1;
} else if (ret == -1) {
// error
printf("traceroute: error receiving packet: %s\n", strerror(errno));
return;
} else {
// continue
}
// increase ttl
mTtl++;
// check if max ttl reached
if (mTtl > 30) {
printf("traceroute: max ttl reached\n");
break;
}
}
}
```
4. 实现 Traceroute 类的 sendPacket 和 receivePacket 方法。
```c++
void Traceroute::sendPacket(int ttl) {
struct icmp* icmp;
int len;
// set packet data
icmp = (struct icmp*)mPacket;
icmp->icmp_type = ICMP_ECHO;
icmp->icmp_code = 0;
icmp->icmp_id = getpid();
icmp->icmp_seq = ttl;
memset(icmp->icmp_data, 0xa5, PACKETSIZE - sizeof(struct icmp));
// set packet length
len = sizeof(struct icmp) + PACKETSIZE - sizeof(struct icmp);
// send packet
gettimeofday(&mStartTime, NULL);
if (sendto(mSocket, mPacket, len, 0, (struct sockaddr*)&mDestAddr, sizeof(struct sockaddr_in)) <= 0) {
printf("traceroute: error sending packet: %s\n", strerror(errno));
return;
}
}
int Traceroute::receivePacket(int ttl) {
struct sockaddr_in addr;
socklen_t addrlen;
struct ip* ip;
struct icmp* icmp;
int len;
int ret;
// set timeout
mTimeout.tv_sec = 1;
mTimeout.tv_usec = 0;
// clear read set
FD_ZERO(&mReadSet);
FD_SET(mSocket, &mReadSet);
// select
ret = select(mSocket + 1, &mReadSet, NULL, NULL, &mTimeout);
if (ret == 0) {
// timeout
printf("%2d * *\n", ttl);
return 1;
} else if (ret < 0) {
// error
return -1;
}
// receive packet
addrlen = sizeof(struct sockaddr_in);
len = recvfrom(mSocket, mPacket, PACKETSIZE, 0, (struct sockaddr*)&addr, &addrlen);
if (len < 0) {
printf("traceroute: error receiving packet: %s\n", strerror(errno));
return -1;
}
// check packet length
ip = (struct ip*)mPacket;
if (len < (int)(ip->ip_hl * 4 + sizeof(struct icmp))) {
printf("traceroute: packet too short\n");
return -1;
}
// check packet type
icmp = (struct icmp*)(mPacket + ip->ip_hl * 4);
if (icmp->icmp_type == ICMP_ECHOREPLY) {
// received reply
gettimeofday(&mEndTime, NULL);
timersub(&mEndTime, &mStartTime, &mTimeDiff);
printf("%2d ", ttl);
printAddress(addr);
printf(" %.3f ms\n", mTimeDiff.tv_sec * 1000.0 + mTimeDiff.tv_usec / 1000.0);
return 0;
} else if (icmp->icmp_type == ICMP_TIME_EXCEEDED) {
// received time exceeded
printf("%2d ", ttl);
printAddress(addr);
printf(" *\n");
return 1;
} else {
// received unknown packet
printf("traceroute: unknown packet type: %d\n", icmp->icmp_type);
return -1;
}
}
```
5. 在 Java 代码中调用 C++ 的 traceroute 方法。
```java
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("traceroute");
}
private static final String HOSTNAME = "www.google.com";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Traceroute traceroute = new Traceroute(HOSTNAME);
traceroute.run();
}
}
```
注意,为了在 Android 应用程序中使用 C++,需要使用 Android NDK。在你的 Android 项目中添加一个名为 jni 的文件夹,并在其中创建一个名为 Android.mk 的文件和一个名为 traceroute.cpp 的文件。Android.mk 文件应该包含以下内容:
```makefile
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := traceroute
LOCAL_SRC_FILES := traceroute.cpp
include $(BUILD_SHARED_LIBRARY)
```
然后,可以使用 ndk-build 命令编译 C++ 代码,并将生成的共享库文件添加到 Android 项目中。
阅读全文