大家都知道wry.dll这个文件吧,它就是一张全球的IP地址分配表,里边有IP地址对应的地理位置,利用这张表,可以轻松的根据你知道的IP查到它的地址位置.它虽然定义成了一个DLL文件,但是实际上它是一个数据库,这篇文章就是告诉大家它的结构,并且写一个查询的程序例子.如果你已经知道了,或者不屑知道这么简单的玩艺,呵呵,请离开.^_^
程序的主要思路很简单,根据IP或者HOST来逐条比较每条WRY.DLL中的数据,若符合条件,则显示信息.此程序必须有WRY.DLL文件.
wry.dll由若千条记录组成,既然是记录,那么它就有其结构,实际上每一条记录包含5个字段,分别是STARTIP(17),ENDIP(17),COUNTRY(16),LOCAL(54),THANK(23),括号里边的是该字段的长度,以字节为单位.各个字段的含义如下:
STARTIP: 一个IP地址段的起始地址 ENDIP: 一个IP地址段的终止地址 COUNTRY: 该地址段所在的国家 LOCAL: 该地址段所在的国家的具体位置 THANK: 此项信息的提供者
好了,既然知道了记录的结构,那么我们就可以定义它的数据结构如下:
struct _wry{ char startip[17]; char endip[17]; char country[16]; char local[54]; char thank[23]; };
接下来,知道了这个最重要的信息,我们就可以编写程序来根据IP或者是host来显示信息了.
但是,字符串的IP地址长度最长为15(xxx.xxx.xxx.xxx),而为什么记录中的startip和endip的长度都定义成17了呢?如果呢编写简单的程序来测试一些就知道,这两个字段的第一个字符都为空格,最后一个字符为NULL,真正的地址是从第二个字符开始的,即&(startip[1]),认识到这一点也非常重要.
此外,每条记录中的IP字符串长度都为15,即是11.123.11.2形式的IP串在里边的形式为011.123.011.002,那么如果不将要查询的IP串进行转化,比较起来就比较麻烦,因此需要由一个函数将IP串转化成15长度的标准格式.
还有,WRY.DLL文件中不是所有的记录都是如上的结构,特殊的就是第一个记录,经过测试,得知它的长度是320-128=192,而其它的所有记录的长度均为128.
最后一个问题就是如果单纯的这样查询比较:if(startip < 查询的i <endip) 打印信息,那么就可能显示除若干条,因为里边的IP并不是非常严格的.
好了,所有的需要注意的地方都提到了,下边就开始写程序吧. 写好的代码如下: ********************************************************************************************** file://in wry.dll,the startip and endip format is :[ 000.000.000.000 ] file://len = 17,and the first is BLANK and the last is NULL
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <conio.h> #include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
struct _wry{ char startip[17]; char endip[17]; char country[16]; char local[54]; char thank[23]; };
struct _wry *wry;
char str[320]; char temp[16]; struct _wry maxw[10]; int count = 0;
char* convertip(const char* ip) { char *temp2; int i,j;
strcpy(temp,"000.000.000.000"); temp2 = (char*)malloc(strlen(ip)); strcpy(temp2,ip);
j = strlen(temp2); for( i =0 ; i < j; i++) if(temp2[i] == '.') temp2[i] = '\0';
for(i = 0; i < 4; i++) { strncpy(&temp[i*4+3-strlen(temp2)],temp2,strlen(temp2)); temp2 += strlen(temp2) +1; }
return temp; }
int do_dis(const char *ip) { if(strncmp(&(wry->endip [1]),ip,strlen(ip)) <= 0) return 0;
if(strncmp(&(wry->startip [1]),"000.000.000.000",15) == 0) return 0;
if(strncmp(&(wry->startip [1]),ip,strlen(ip)) <= 0) memcpy(&maxw[count++],wry,sizeof(struct _wry)); return 1;
}
void main(int argc,char **argv) { WSADATA wsd; struct hostent *h = NULL; FILE * fp = NULL; int i = 0; char cip[16];
if(argc != 2) { printf("usage %s [ip | host]\n",argv[0]); return; }
if(WSAStartup(MAKEWORD(2,2),&wsd) != 0) return; if(inet_addr(argv[1]) == INADDR_NONE) { if((h = gethostbyname(argv[1])) != NULL) strcpy(cip,inet_ntoa(*(struct in_addr*)h->h_addr)); else { printf("resolve host to ip failed\n"); return; } } else strcpy(cip,argv[1]); convertip(cip); printf("\n****************************************************\n"); printf("convert ip: %s\n",temp);
if((fp = fopen("wry.dll","r")) == NULL) { printf("can not open file!"); exit(0); }
while(!feof(fp)) {
if( i == 0) { if(fread(str,sizeof(str) - 128,1,fp) != 1) { printf("read file error\n"); exit(0); } else i = 1;
continue; } else if(fread(str,128,1,fp) != 1) { file://read end of file }
wry = (struct _wry*)str; wry->thank [23] = '\0'; wry->local [53] = '\0'; wry->country [15] = '\0'; wry->endip [16] = '\0'; wry->startip [16] = '\0'; do_dis(temp); }
fclose(fp); WSACleanup();
if(count == 0) printf("not match found!\n"); else { printf("found %d match,and the best match as follows:\n",count); printf("==========================\n"); printf("startip:%s\n",maxw[--count].startip ); printf("endip:%s\n",maxw[count].endip ); printf("country:%s\n",maxw[count].country ); printf("local:%s\n",maxw[count].local ); printf("****************************************************\n\n"); }
} *********************************************************************************************** 此程序在windows 2000 和VC6.0下编译通过,编译好的程序和代码,以及WRY.DLL文件可以在地址
http://blldw.myetang.com/vc/hunt.zip下载.
感谢你看到了最后!^_^. any problem please mailto: [email protected].
2002.7.28

|