整理硬盘看到以前写的纯真ip数据库(QQWry.Dat)查询代码,觉得没有什么价值了,当时学习C语言的文件操作时自己的一个练习而已,现在公布出来希望对学习C语言的人有所参考价值.
纯真ip数据库(QQWry.Dat)是当年很多修改版QQ使用的显示对方所在地的ip数据库,该数据库由纯真维护着,ip地址所在地是许多网友提交才发展那么强大的,参考lumaqq的一些资料会有帮助:
纯真ip地址查询java代码
lumaqq文档整理
好了不多说了代码如下:
MakeFile
CC = gcc.exe
BIN = qqwry.exe
WINDRES = windres.exe
RES = resource.o
OBJ = main.o qqwry.o localIp.o $(RES)
# D:\MinGW\lib\libwsock32.a
LIBS = -L"D:/MinGW/lib"-lwsock32
RM = del -f
$(BIN): $(OBJ)
$(CC) -o $(BIN) $(OBJ) $(RES) $(LIBS)
main.o: main.h qqwry.h
qqwry.o: qqwry.h localIp.h
localIp.o: localIp.h
$(RES): resource.rc my_icon.ico
$(WINDRES) -o $(RES) resource.rc
.PHONY:clean
clean:
$(RM) $(BIN) $(OBJ) *~
main.c
/**
*
* 增加了解压数据库功能,包括
* void readIpString(char *string);
* void exportData(char *fileName);
*
* @author http://www.heui.org
* @version 0.6
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "qqwry.h"
FILE*ipFile = NULL; //ip文件指针
unsigned longipBegin = 0; //ip开始地址
unsigned longipEnd = 0; //ip结束地址
unsigned longipSum = 0; //ip总数
/**
* main()
*/
int main(int argc, char** argv)
{
ipFile = fopen("QQWry.Dat", "rb");
if(!ipFile){
puts("QQWry.Dat文件丢失");
exit(1);
}
unsigned longdata[2];
fread(data, 1, 8, ipFile);
ipBegin = data[0];
ipEnd = data[1];
ipSum = ((data[1]-data[0])/RECORD_LENGTH +1);
checkCmdLine(argc, argv);//处理命令行参数
fclose(ipFile);
return0;
}
qqwry.h
#ifndef QQWRY_H
#define QQWRY_H
#define RECORD_LENGTH 0x07 //ip记录长度
#define AREA_FOLLOWED 0X01 //模式1
#define NO_AREA 0x02 //模式2
typedefstructipInfo
{
charipBegin[15]; //ip段开始地址
charipEnd[15]; //ip段结束地址
charcountryAndArea[255]; //ip段对应的国家和地区
} ipInfo;
unsigned longstringIpToLong(char*ipString);
unsigned longseekIpBinarySearch(char*ipString);
voidreadString(char*string, unsigned longoffset);
voidreadStringCur(char*string);
voidseekCountryArea(char*string, unsigned longoffset);
voidreadArea(char*string);
voidcheckCmdLine(intargc, char**argv);
voidreadIpString(char*string);
voidexportData(char*fileName);
voidsearchIpByName(char*name);
#endif
qqwry.c
/**
* 重新写了stringIpToLong函数,改用sscanf,增加了判断ip地址错误
* @author http://www.heui.org
* @version 0.8
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "qqwry.h"
#include "localIp.h"
externFILE*ipFile;
externunsigned longipBegin, ipEnd, ipSum;
/**
* 把ip字符串转换为unsigned long
* @param char *ipString
* @return unsigned long ret
*/
unsigned longstringIpToLong(char*ipString)
{
intnum[4];
charch =0;
unsigned longret = 0;
if(sscanf(ipString, "%3d.%3d.%3d.%3d%c",&num[0], &num[1], &num[2], &num[3], &ch) != 4
// || ch != 0 //sscanf返回 !=4包括了ch不为0
|| num[0] > 0xFF
|| num[1] > 0xFF
|| num[2] > 0xFF
|| num[3] > 0xFF
|| num[0] < 0x00
|| num[1] < 0x00
|| num[2] < 0x00
|| num[3] < 0x00){
puts("ip地址错误");
exit(0);
}
ret = ret | (num[0] << 24) | (num[1] << 16) | (num[2] << <img src="http://www.heui.org/wp-includes/images/smilies/icon_cool.gif "alt="8)"class="wp-smiley"> | (num[3]);
/*
char tmp[16];
unsigned long ret = 0;
strcpy(tmp, ipString);
char *str = strtok(tmp, ".");
ret = ret | (atol(str) << 24);
str = strtok(NULL, ".");
ret = ret | (atol(str) << 16);
str = strtok(NULL, ".");
ret = ret | (atol(str) << 8);
str = strtok(NULL, ".");
ret = ret | (atol(str));
*/
returnret;
}
/**
* 返回ip记录所在位置,使用二分法
* @param char *ipString
* @return unsigned long
*/
unsigned longseekIpBinarySearch(char*ipString)
{
unsigned longipNum = stringIpToLong(ipString);
unsigned longstart = 0L;
unsigned longend = ipSum;
unsigned longmid = 0L;
unsigned longaddr[2] = {0L};
while(start != end) {
mid = (start + end) / 2;
fseek(ipFile, ipBegin + mid * RECORD_LENGTH, SEEK_SET);
fread(addr, 1, 7, ipFile);
if(ipNum == addr[0]) {
returnaddr[1];
} elseif(end == start +1) {
returnaddr[1];
} elseif(ipNum > addr[0]){
start = mid;
} else/* if(ipNum > addr[0])*/{
end = mid;
}
}
}
/**
* 从文件offset位置读取字符串到string,直到遇到空字符
* @param char *string
* @param unsigned long offset
* @return void
*/
voidreadString(char*string, unsigned longoffset)
{
fseek(ipFile, offset, SEEK_SET);
while(*string++ = fgetc(ipFile))
;
}
/**
* 从文件当前位置读取字符串到string,直到遇到空字符
* @param char *string
* @param unsigned long offset
* @return void
*/
voidreadStringCur(char*string)
{
while(*string++ = fgetc(ipFile))
;
}
/**
* 从文件offset位置读取国家地区到string
* @param char *string
* @param unsigned long offset
* @return void
*/
voidseekCountryArea(char*string, unsigned longoffset)
{
fseek(ipFile, offset+4, SEEK_SET);
charflag = fgetc(ipFile);
unsigned longcountryOffset[1] = {0L};
if(AREA_FOLLOWED == flag) {
fread(countryOffset, 1, 3, ipFile);
fseek(ipFile, countryOffset[0], SEEK_SET);
flag = fgetc(ipFile);
if(NO_AREA == flag) {
unsigned longtmp = countryOffset[0];
fread(countryOffset, 1, 3, ipFile);
fseek(ipFile, countryOffset[0], SEEK_SET);
readStringCur(string);
string = strcat(string, " ");
fseek(ipFile, tmp+4, SEEK_SET);
} else{
fseek(ipFile, -1, SEEK_CUR);
readStringCur(string);
string = strcat(string, " ");
}
} elseif(NO_AREA == flag){
fread(countryOffset, 1, 3, ipFile);
readString(string, countryOffset[0]);
string = strcat(string, " ");
fseek(ipFile, offset+8, SEEK_SET);
} else{
readString(string, offset+4);
string = strcat(string, " ");
}
readArea(string);
}
/**
* 读取地区字符串到string后面,具体是加在国家字符串后面
* @param char *string
* @return void
*/
voidreadArea(char*string)
{
unsigned longoffset[1] = {0L};
chararea[255] = "";
int flag = fgetc(ipFile);
if(AREA_FOLLOWED == flag || NO_AREA == flag) {
fread(offset, 1, 3, ipFile);
readString(area, offset[0]);
string = strcat(string, area);
} else{
fseek(ipFile, -1, SEEK_CUR);
readStringCur(area);
string = strcat(string, area);
}
}
/**
* 检查命令行输入参数
*/
voidcheckCmdLine(intargc, char**argv){
if(argc == 1) {
//数据库信息
unsigned longll = seekIpBinarySearch("255.255.255.0");
charstring[255]="";
seekCountryArea(string,ll);
printf("%s %lu条\n", string, ipSum);
//输出你的ip地址
localIp(string);
printf("\n你的IP:%s\n",string);
ll = seekIpBinarySearch(string);
seekCountryArea(string,ll);
printf("IP地址:%s\n",string);
//帮助
puts("----------------------------------------");
puts("查询ip地址");
printf("\n用法:\%s ip地址\n例如:%s 127.0.0.1\n", argv[0], argv[0]);
puts("\n解压数据库");
printf("\n用法:\%s -o 文件名\n例如:%s -o qqwry.txt\n", argv[0], argv[0]);
puts("\n搜索字符串");
printf("\n用法:\%s -s 字符串\n例如:%s -s 浏阳\n", argv[0], argv[0]);
puts("----------------------------------------");
exit(1);
//搜索ip记录
}elseif(argc==2){
puts(argv[1]);
charstring[255]="";
unsigned longll = seekIpBinarySearch(argv[1]);//二分法搜索ip记录位置
seekCountryArea(string, ll);//从ll位置读取ip记录信息
puts(string);
}elseif(argc == 3 ){
//导出记录
if(strcmp(argv[1],"-o")==0){
puts("准备导出");
//文件已经存在(,还需要判断是否可写,不然崩溃)
if(access(argv[2],F_OK) == 0){
printf("是否覆盖%s(Y/N)",argv[2]);
charch = 0;
while( (ch = tolower(getchar())) != 'y'&& ch !='n') {
printf("是否覆盖%s(Y/N)",argv[2]);
}
if(ch =='n')
exit(1);
}
exportData(argv[2]);
}elseif(strcmp(argv[1],"-s")==0){
searchIpByName(argv[2]);
}else{
puts("有任何问题请联系:hehuiahui@163.com");
}
//其他
}else{
puts("有任何问题请联系:hehuiahui@163.com");
}
}
/**
* 从当前位置读取4个字节转换为ip字符串
* @param char *string 保存ip字符串
*/
voidreadIpString(char*string)
{
// if(sizeof(string) < 16)
// realloc(string, 16);
sprintf(string, "%d.%d.%d.%d", fgetc(ipFile), fgetc(ipFile), fgetc(ipFile), fgetc(ipFile));
// free(string);
}
/**
* 导出记录
* @param char *filename 文件名
*
*/
voidexportData(char*fileName)
{
FILE*fp = fopen(fileName, "wb");
unsigned longi=0;
unsigned longdata[1]={0};
charstring[255]="";
unsigned longdi = (ipSum/100);
intj=0;
while(!feof(ipFile) && i != ipSum){
//起始ip
fseek(ipFile, ipBegin + RECORD_LENGTH * i, SEEK_SET);
readIpString(string);
fprintf(fp, "%-16s", string);
//结束ip
fread(data, 1, 3, ipFile);
fseek(ipFile, data[0], SEEK_SET);
readIpString(string);
fprintf(fp, "%-16s", string);
//国家地区
seekCountryArea(string, data[0]);
fputs(string, fp);
fputs("\r\n",fp); // \r\n for windows
//导出进度
if(i%di==0){
if(j>9)
putchar('\b');
putchar('\b');
putchar('\b');
if(j%2==0)
putchar('#');
printf("%d%%",j++);
}
++i;
}
puts("\n导出完毕");
}
/**
* 搜索国家地区中包含某字符串的ip段
* @param char *name 要搜索的字符串
*/
voidsearchIpByName(char*name)
{
unsigned longi=0;
unsigned longdata[1]={0};
charstring[255]="";
unsigned longj=0;
intk=0;
while(!feof(ipFile) && i != ipSum){
fseek(ipFile, ipBegin + RECORD_LENGTH * i +4, SEEK_SET);
fread(data, 1, 3, ipFile);
seekCountryArea(string, data[0]);
if(strstr(string, name) != NULL) {
while(k>0){
putchar('\b');
--k;
}
charipStr[16]="";
fseek(ipFile, ipBegin + RECORD_LENGTH * i, SEEK_SET);
readIpString(ipStr);
printf("%-16s", ipStr);
fread(data, 1, 3, ipFile);
fseek(ipFile, data[0], SEEK_SET);
readIpString(ipStr);
printf("%-16s", ipStr);
puts(string);
++j;
}else{
//等待
if(i%(ipSum/50)==0){
putchar('>');
++k;
}
}
++i;
}
while(k>0){
putchar('\b');
--k;
}
printf("总共搜索到 %lu 条记录。 ",j);
}
localIp.h
#ifndef LOCAL_IP_H
#define LOCAL_IP_H
intlocalIp(char*ip);
#endif
localIp.c
/**
* 获取本机ip地址
*
* 需要指定wsock32.lib
* gcc需要指定libwsock32.a
* @author http://www.heui.org
* @version 0.1
*/
#include <winsock2.h>
#include <wsipx.h>
//#include "wsnwlink.h"
#include <stdio.h>
#include "localIp.h"
intlocalIp(char*ip)
{
////////////////
// Initialize windows sockets API. Ask for version 1.1
//
WORDwVersionRequested = MAKEWORD(1, 1);
WSADATA wsaData;
if(WSAStartup(wVersionRequested, &wsaData)) {
printf("WSAStartup failed %s\n", WSAGetLastError());
return-1;
}
//////////////////
// Get host name.
//
charhostname[256];
intres = gethostname(hostname, sizeof(hostname));
if(res != 0) {
printf("Error: %u\n", WSAGetLastError());
return-1;
}
////////////////
// Get host info for hostname.
//
structhostent* pHostent = gethostbyname(hostname);
if(pHostent==NULL) {
printf("Error: %u\n", WSAGetLastError());
return-1;
}
structsockaddr_in sa;
intnAdapter;
char*addr;
for(nAdapter=0; pHostent->h_addr_list[nAdapter]; nAdapter++) {
memcpy( &sa.sin_addr.s_addr, pHostent->h_addr_list[nAdapter],pHostent->h_length);
addr =inet_ntoa(sa.sin_addr);
// Output the machines IP Address.
// printf("Address: %s\n", addr =inet_ntoa(sa.sin_addr)); // display as string
}
memcpy(ip,addr,16);
//////////////////
// Terminate windows sockets API
//
WSACleanup();
return0;
}
/*
int main()
{
char ip[16];
localIp(ip);
printf("%s",ip);
return 0;
}*/
resource.rc
A ICON "my_icon.ico"
代码打包下载:纯真ip数据库(QQWry.Dat)查询源代码C语言版 qqwry0.82
转载自:纯真ip数据库(QQWry.Dat)查询源代码C语言版