代码改变世界

显示dos命令ping和tracert等输出结果中的ip对应的地域名称

2012-11-26 21:28  menggucaoyuan  阅读(1346)  评论(2编辑  收藏

  公司老大今天使用了dos命令ping,他想看到其中ip地址对应的地域名称。

  如dos下命令ping www.qq.com的输出结果是:

正在 Ping www.qq.com [113.108.20.50] 具有 32 字节的数据:

正在 Ping www.qq.com [113.108.20.50] 具有 32 字节的数据:
来自 113.108.20.50 的回复: 字节=32 时间=3ms TTL=52
来自 113.108.20.50 的回复: 字节=32 时间=3ms TTL=52
来自 113.108.20.50 的回复: 字节=32 时间=2ms TTL=52
来自 113.108.20.50 的回复: 字节=32 时间=3ms TTL=52


113.108.20.50 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):

    最短 = 2ms,最长 = 3ms,平均 = 2ms

 

  如果上面的输出结果中每个ip后面跟着相应的地域名称是不是更好点?

  老大给了一个url  https://www.surfchen.org/nali,这位老兄使用了纯真ip数据库,给出了linux下的相应实现。

  有了相应的参考,我们便可以实现windows下的相应实现了,详细步骤如下:

  1 创建匿名管道,截获相应dos命令输出结果的每一行的字符串,如果输出为空,则退出,否则进行下面步骤;

  2 提取出字符串中的ip地址,如果没有ip地址,直接跳到第5步;

  3 调用纯真ip数据库的相关接口获取相应的地域名称;

  4 把地域名称字符串插入到原字符串的后面,形成新字符串,输出;

  5回到第一步。

  上面的关键在于创建匿名管道,然后截取字符串中的ip地址。

  我使用了VC2010创建了相关工程,如果要在Debug模式下进行调试,注意把数据库QQWry.Dat复制到工程的Debug目录下面。

  发布的时候,把程序tr.exe和QQWry.Dat放在一个目录下发布,其使用格式是tr dos command 或 tr.exe dos command,如tr ping www.qq.com,其结果如下:

正在 Ping www.qq.com [113.108.20.50  广东省深圳市 电信] 具有 32 字节的数据:
来自 113.108.20.50  广东省深圳市 电信 的回复: 字节=32 时间=3ms TTL=52
来自 113.108.20.50  广东省深圳市 电信 的回复: 字节=32 时间=3ms TTL=52
来自 113.108.20.50  广东省深圳市 电信 的回复: 字节=32 时间=3ms TTL=52
来自 113.108.20.50  广东省深圳市 电信 的回复: 字节=32 时间=3ms TTL=52

  如果要输出命令tracert的结果相关地域名称,使用命令就是tr tracert www.qq.com 或 tr.exe tracert www.qq.com。

  我的email是alexstocks@foxmail.com,欢迎要程序或者报告bug。

  一些关键的源码如下:

  

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "./qqwry.h"
#include <Windows.h>

#define NALI_QQWRY_PATH "./QQWry.Dat"

#define PIPE_BUFFER_SIZE 1024
typedef struct pipe_info_tag {
HANDLE pipe;
char buffer[PIPE_BUFFER_SIZE];
} pipe_info_t;

pipe_info_t pipe_out = {INVALID_HANDLE_VALUE, "\0"};
pipe_info_t pipe_err = {INVALID_HANDLE_VALUE, "\0"};

unsigned int get_host_ip(char* str, char** ip_start, char** ip_end, char* ip);
unsigned int get_ip_city_string(char* ip);
unsigned int read_from_pipe(void* args);

int main(int argc, char *argv[])
{
HANDLE cur_proc_handle = NULL;
HANDLE pipe_handle = NULL;
HANDLE pipe_thread[2] = {NULL, NULL};
PROCESS_INFORMATION proc_info;
SECURITY_ATTRIBUTES security_attr;
STARTUPINFO start_info;
char cmd_line[1024] = {0};
int ret = 0;
char err_msg[1024] = {0};
unsigned int thread_id = 0;
int idx = 0;

cur_proc_handle = GetCurrentProcess();
memset(&proc_info, 0, sizeof(proc_info));
memset(&security_attr, 0, sizeof(security_attr));
memset(&start_info, 0, sizeof(start_info));

start_info.cb = sizeof(STARTUPINFO);
start_info.dwFlags = STARTF_USESTDHANDLES;
start_info.hStdInput = INVALID_HANDLE_VALUE;

security_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
security_attr.lpSecurityDescriptor = NULL;
security_attr.bInheritHandle = TRUE;

CreatePipe(&(pipe_out.pipe), &pipe_handle, &security_attr, 0);
DuplicateHandle(cur_proc_handle, pipe_handle, cur_proc_handle, &(start_info.hStdOutput), 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);


CreatePipe(&(pipe_err.pipe), &pipe_handle, &security_attr, 0);
DuplicateHandle(cur_proc_handle, pipe_handle, cur_proc_handle, &(start_info.hStdOutput), 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);

strcpy(cmd_line, "");
for (idx = 1; idx < argc; idx++) {
strcat(cmd_line, argv[idx]);
strcat(cmd_line, " ");
}
if (0 == strlen(cmd_line)) {
strcpy(cmd_line, "ping www.qq.com");
}
ret = CreateProcess(NULL, cmd_line, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &start_info, &proc_info);
if (ret == 0) {
unsigned int err_no = GetLastError();
int err_msg_len = _snprintf(err_msg, sizeof(err_msg) - 1, "Tried to launch: \"%s\", but get error [%u]: ", cmd_line, err_no);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, err_no, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &err_msg[err_msg_len], 0, NULL);
return 1;
}

CloseHandle(start_info.hStdOutput);
CloseHandle(start_info.hStdError);

WaitForInputIdle(proc_info.hProcess, 5000);
CloseHandle(proc_info.hThread);

pipe_thread[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)read_from_pipe, &pipe_out, 0, (LPDWORD)&thread_id);
pipe_thread[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)read_from_pipe, &pipe_err, 0, (LPDWORD)&thread_id);

WaitForSingleObject(proc_info.hProcess, INFINITE);
CloseHandle(proc_info.hProcess);

WaitForMultipleObjects(2, pipe_thread, TRUE, INFINITE);
CloseHandle(pipe_thread[0]);
CloseHandle(pipe_thread[1]);

return 0;
}


unsigned int read_from_pipe(void* args) {
pipe_info_t* pipe_info = (pipe_info_t*)(args);
char* last_buf = NULL;
unsigned int read = 0;
int ret = 0;
char tmp_buf[1024] = {0};
char buf[1024] = {0};
char pre_ip_string[1024] = {0};
char post_ip_string[1024] = {0};
char ip_string[1024] = {0};
char ip[10] = {0};
char* ip_start = NULL;
char* ip_end = NULL;
if (NULL == args) {
return 1;
}

while (1) {
memset(ip, 0, sizeof(ip));
ret = ReadFile(pipe_info->pipe, buf, sizeof(buf), (LPDWORD)&read, 0L);
if (ret == 0 || read == 0) {
CloseHandle(pipe_info->pipe);
break;
}
buf[read] = '\0';
//printf("%s", buf);
memset(tmp_buf, 0, sizeof(tmp_buf));
memset(ip, 0, sizeof(ip));
ret = get_host_ip(buf, &ip_start, &ip_end, ip);
if (ret == 1 && NULL != ip_end) {
memset(tmp_buf, 0, sizeof(tmp_buf));
memcpy(tmp_buf, buf, ip_end - buf);
printf("%s", tmp_buf);
get_ip_city_string(ip);
printf("%s", ip_end);
} else {
printf("%s", buf);
}
}

return 0;
}

unsigned int get_host_ip(char* str, char** ip_start, char** ip_end, char* ip) {
char buf[4] = {0};
int runnum = 0;
int ret = 0;
int idx = 0;
int start = 0;
int str_len = strlen(str);
int num = 0;
int ip_idx = 0;
int ip_num[32] = {0};

while (1) {
*ip_start = NULL;
*ip_end = NULL;
runnum++;
//get the first number index
if (1 < runnum) {
ret = 0;
for (idx = start + 1; idx < str_len; idx++) {
if (str[idx] < '1' || '9' < str[idx]) {
start = idx;
*ip_start = str + idx;
ret = 1;
break;
}
}

if (ret == 0) {
break;
}
}

//get the first number index
ret = 0;
for (idx = start; idx < str_len; idx++) {
if ('1' <= str[idx] && str[idx] <= '9') {
start = idx;
*ip_start = str + idx;
ret = 1;
break;
}
}

if (ret == 0) {
break;
}

//check whether there are three "."
num = 0;
for (idx = start; idx < str_len; idx++) {
if (str[idx] == '.') {
num++;
}
}
if (num < 3) {
ret = 0;
break;
}

ret = 0;
memset(buf, 0, sizeof(buf));
for (idx = start, ip_idx = 0, num = 0; idx < str_len; idx++) {
//get ip number string, its max length is 3
if ('0' <= str[idx] && str[idx] <= '9') {
if (num < 3) {
buf[num] = str[idx];
*ip_end = str + idx +1;
ret = 1;
} else {
ret = 0;
break;
}
num++;
} else if (str[idx] == '.') {
if (strlen(buf) == 0) {
ret = 0;
break;
}

ip_num[ip_idx] = atoi(buf);
if (ip_num[ip_idx] <= 255) {
ip_idx++;
num = 0;
memset(buf, 0, sizeof(buf));
if (ip_idx == 4) {
ret = 1;
break;
}
} else {
ret=0;
break;
}
} else {
break;
}
}

if (ip_idx == 3) {
if (ret == 1) {
if (strlen(buf)==0) {
ret=0;
} else {
ip_num[3] = atoi(buf);
if (ip_num[3] <= 255) {
ret = 1;
} else {
ret = 0;
}
}
}
} else {
if (ip_idx != 4) {
ret=0;
}
}

if (ret == 1) {
break;
} else {
continue;
}
}

if (ret == 1) {
sprintf(ip, "%u.%u.%u.%u", ip_num[0], ip_num[1], ip_num[2], ip_num[3]);
}

return ret;
}

unsigned int get_ip_city_string(char* ip) {
FILE* wry_file = NULL;
int idx = 0;
char country[1024] = {"\0"};
char area[1024] = {"\0"};

if (NULL == ip || strlen(ip) == 0) {
return 0;
}

for (idx = 0; idx < 2; ++idx) {
if (idx == 0) {
wry_file = fopen(NALI_QQWRY_PATH, "r");
} else if (idx == 1) {
wry_file=fopen("./QQWry.Dat","r");
}
if (wry_file!=NULL) {
break;
}
}
qqwry_get_location(country, area, ip, wry_file);
fclose(wry_file);
if (0 < strlen(country)) {
printf(" %s",country);
}
if (0 < strlen(area)) {
if (0 < strlen(country)) {
printf(" ");
}
if (strlen(country) <= 0) {
printf("unknown");
} else {
printf("%s",area);
}
}
//printf("\n");
return 0;
}