争取一天看一个文件,随便找一个好看的看起eva/src/api/evaipseek
#ifndef EVAIPSEEKER_H #define EVAIPSEEKER_H #include <string> #include <fstream> //一看头文件,只有file操作,看来不是socket相关 class EvaIPSeeker { public: EvaIPSeeker(); EvaIPSeeker(std::string absPath); ~EvaIPSeeker(); const std::string getIPLocation(const std::string ip); const std::string getIPLocation(const unsigned int ip); const bool isQQWryExisted(); private: unsigned int searchIP(const unsigned int ip); unsigned int readIP(unsigned int offset); unsigned int getMiddleOffset(const unsigned int begin, const unsigned int end); int compareIP(const unsigned int ip1, const unsigned int ip2); std::string getIPRecord(const unsigned int offset); std::string readString(const unsigned int offset); std::string readArea(const unsigned int offset); bool getIndexOffset(std::fstream& inputfile); private: std::fstream ipFile; //file i/o stream std::string fileName; //the data file path int firstIndexOffset; //the first index offset of the index area int lastIndexOffset; //the last index offset of the index area char byte4[4]; //tmp char array char byte3[3]; //tmp char array }; #endif
/*************************************************************************** * Copyright (C) 2005 by casper * * tlmcasper@163.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include <iostream> #include <string> #include <fstream> #include "evaipseeker.h" #include "evaipaddress.h"//这里还依赖一个文件,看来得看看这个 #define STRING_LEN 80 #define IP_RECORD_LENGTH 7 #define REDIRECT_MODE_1 0x01 #define REDIRECT_MODE_2 0x02 #define DATAFILENAME "QQWry.dat" //qq直接用文件,都不用sql #define READINT3(X) (( X[0] & 0xFF )|(( X[1] & 0xFF)<< 8 )|(( X[2] & 0xFF )<< 16 )) //用移位操作的都是高手,是否? #define READINT4(X) (( X[0] & 0xFF )|(( X[1] & 0xFF)<< 8 )|(( X[2] & 0xFF )<< 16 )|(( X[3] & 0xFF ) << 24 )) using namespace std; //get the path of IP data file which is in the working directory,store in @fileName //param:null //return:null EvaIPSeeker::EvaIPSeeker() { fileName = DATAFILENAME; } //get the absolute path of IP data file,store it in @fileName; //param: string absPath //return: null EvaIPSeeker::EvaIPSeeker(string absPath) { fileName = absPath + "/" + DATAFILENAME; } //check the status of IP data file,close it if it opened. //param: null //return: null EvaIPSeeker::~EvaIPSeeker() { if(ipFile.is_open()) ipFile.close(); } //check if QQWry.dat exists //param: null //return: true or false const bool EvaIPSeeker::isQQWryExisted() { ipFile.open(fileName.c_str(), ios::in); if(!ipFile) return false; else { ipFile.close(); return true; } } //search ip in the index area of IP data file,return the offset of IP record if found. //param: unsigned int ip //return: unsigned int offset unsigned int EvaIPSeeker::searchIP(const unsigned int ip) { unsigned int startIP; unsigned int endIP; unsigned int midIP,mOffset; int r; unsigned int i,j; startIP = readIP(firstIndexOffset); endIP = readIP(lastIndexOffset); r = compareIP(ip,startIP); if(r == 0) return firstIndexOffset; else if(r < 0) return 0; for(i = firstIndexOffset, j = lastIndexOffset; i < j;) { mOffset = getMiddleOffset(i, j); midIP = readIP(mOffset); r = compareIP(ip, midIP); if(r > 0) i = mOffset; else if(r < 0) { if(mOffset == j) { j -= IP_RECORD_LENGTH; mOffset = j; } else j = mOffset; } else { if(!ipFile.is_open()) ipFile.open(fileName.c_str(), ios::in|ios::binary); ipFile.seekg(mOffset+4, ios::beg); ipFile.read(byte3, 3); ipFile.close(); return READINT3(byte3); } } if(!ipFile.is_open()) ipFile.open(fileName.c_str(), ios::in|ios::binary); ipFile.seekg(mOffset+4, ios::beg); ipFile.read(byte3, 3); midIP = readIP(READINT3(byte3)); r = compareIP(ip, midIP); if(r <= 0) return READINT3(byte3); else return 0; } //read 4 bytes start from the offset,and change them to an IP address. //param: unsigned int offset //return: unsigned int IP unsigned int EvaIPSeeker::readIP(unsigned int offset) { unsigned int tmpIP; if(!ipFile.is_open()) ipFile.open(fileName.c_str(), ios::in|ios::binary); ipFile.seekg(offset, ios::beg); ipFile.read(byte4,4); tmpIP = READINT4(byte4); ipFile.close(); return tmpIP; } //compare two IP //param: unsigned int ip1, unsigned int ip2 //return: int result int EvaIPSeeker::compareIP(const unsigned int ip1, const unsigned int ip2) { if( ip1 > ip2 ) return 1; else if ( ip1 < ip2 ) return -1; else return 0; } //get the middle offset of two offsets. //param: unsigned int begin, unsigned int end //return: unsigned int theMiddleOffset unsigned int EvaIPSeeker::getMiddleOffset(const unsigned int begin, const unsigned int end) { int records = (end - begin) / IP_RECORD_LENGTH; records >>= 1; if(records == 0) records = 1; return begin + records * IP_RECORD_LENGTH; } //read a string start from the offset until meet a char '\0' //param: unsigned int offset //return: string str string EvaIPSeeker::readString(const unsigned int offset) { static char tmpstr[STRING_LEN]; string str; ipFile.seekg(offset, ios::beg); ipFile.getline(tmpstr,STRING_LEN,'\0'); str = tmpstr; return str; } //get one IP record (country and area) of the offset //param: unsigned int offset //return: string location string EvaIPSeeker::getIPRecord(const unsigned int offset) { char flag; string country; string area; string location; unsigned int countryOffset; if(!ipFile.is_open()) ipFile.open(fileName.c_str(), ios::in|ios::binary); ipFile.seekg(offset+4, ios::beg);//ignore the ip data ipFile.get(flag); if(flag == REDIRECT_MODE_1) { ipFile.read(byte3, 3); countryOffset = READINT3(byte3); //get the offset of country data ipFile.seekg(countryOffset); ipFile.get(flag); // check the flag again,maybe it's an other redirectroy if(flag == REDIRECT_MODE_2) { ipFile.read(byte3, 3); country = readString(READINT3(byte3)); ipFile.seekg(countryOffset+4);//if mode2,we need pass 4 bytes to reach the area data; } else { country = readString(countryOffset); } area = readArea(ipFile.tellg()); } else if(flag == REDIRECT_MODE_2) { ipFile.read(byte3, 3); country = readString(READINT3(byte3)); area = readArea(offset+8); } else { ipFile.putback(flag);//make the inside pointer back 1 character country = readString(ipFile.tellg()); area = readArea(ipFile.tellg()); } location = country + area; ipFile.close(); return location; } //read the Area data start from the offset. //param: unsigned int offset //return: string areaData string EvaIPSeeker::readArea(const unsigned int offset) { char flag; unsigned int areaOffset; ipFile.seekg(offset, ios::beg); ipFile.get(flag); if(flag == REDIRECT_MODE_1 || flag == REDIRECT_MODE_2) { ipFile.read(byte3, 3); areaOffset = READINT3(byte3); if(areaOffset != 0) return readString(areaOffset); else return "Unknow Area";//if the areaoffset is zero,it's show there's no data for the area } else return readString(offset); } //get the Index arrange of the Index area from infile //param: fstream& infile //return: true or false bool EvaIPSeeker::getIndexOffset(fstream& infile) { infile.seekg(ios::beg); infile.read(byte4, 4); firstIndexOffset = READINT4(byte4); infile.read(byte4, 4); lastIndexOffset = READINT4(byte4); if(( firstIndexOffset == -1 )||( lastIndexOffset == -1 )) { return false; } return true; } //main function, get the location of an IP address,if IP is not valid or the Data file missed then return IP address. //param: unsigned int ip //return: string location or string ip const string EvaIPSeeker::getIPLocation(const unsigned int ip) { EvaIPAddress addr(ip); if(!isQQWryExisted()) return addr.toString(); ipFile.open(fileName.c_str(), ios::in|ios::binary); if(!ipFile) return addr.toString(); else { if(!getIndexOffset(ipFile)) { ipFile.close(); return addr.toString(); } return getIPRecord(searchIP(addr.IP())); } } //main function, get the location of an IP address,if IP is not valid or the Data file missed then return IP address. //param: string ip //return: string location or string ip const string EvaIPSeeker::getIPLocation(const string ip) { EvaIPAddress addr(ip); if(!addr.isValid()) return addr.toString(); if(!isQQWryExisted()) return addr.toString(); ipFile.open(fileName.c_str(), ios::in|ios::binary); if(!ipFile) return addr.toString(); else { if(!getIndexOffset(ipFile)) { ipFile.close(); return addr.toString(); } return getIPRecord(searchIP(addr.IP())); } }
没看到具体的关键实现,只是一个文件检索。保存了ip,国家,地区信息。忽略之。
#ifndef EVAIPADDRESS_H #define EVAIPADDRESS_H #include <inttypes.h> #include <string> /* this class is only for ipv4 addresses this class can be used as below: EvaIPAddress addr("255.255.255.255"); // or EvaIPAddress addr(0xffffffff) ; uint ip = addr.IP(); std::string strIP = addr.toString(); */ class EvaIPAddress{ public: EvaIPAddress() {}; EvaIPAddress(const uint ip); EvaIPAddress(const std::string &strIP); EvaIPAddress(const EvaIPAddress &address); void setAddress(const uint ip); void setAddress(const std::string &strIP); const bool isValid() const; const uint IP() const; const std::string toString(); EvaIPAddress &operator= (const EvaIPAddress &rhs); private: bool isValidIP; uint mIP; uint getIntIP(const std::string &strIP); }; #endif
看着头文件,也只是一个工具类。
/*************************************************************************** * Copyright (C) 2005 by yunfan * * yunfan_zg@163.com * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "evaipaddress.h" #include <stdlib.h> EvaIPAddress::EvaIPAddress(const uint ip) :isValidIP(false) { mIP = ip; isValidIP = true; } EvaIPAddress::EvaIPAddress(const std::string &strIP) :isValidIP(false) { mIP = getIntIP(strIP); if(mIP) isValidIP = true; } EvaIPAddress::EvaIPAddress(const EvaIPAddress &address) :isValidIP(false) { mIP = address.IP(); isValidIP = address.isValid(); } void EvaIPAddress::setAddress(const uint ip) { mIP = ip; } void EvaIPAddress::setAddress(const std::string &strIP) { mIP = getIntIP(strIP); } const bool EvaIPAddress::isValid() const { return isValidIP; } const uint EvaIPAddress::IP() const { return mIP; } const std::string EvaIPAddress::toString() { char strIP[16]; memset(strIP, 0, 16); sprintf(strIP, "%d.%d.%d.%d", (mIP&0xFF000000)>>24, (mIP&0x00FF0000)>>16, (mIP&0x0000FF00)>>8, (mIP&0x000000FF)); return std::string(strIP); } EvaIPAddress &EvaIPAddress::operator= (const EvaIPAddress &rhs) { mIP = rhs.IP(); isValidIP = rhs.isValid(); return *this; } uint EvaIPAddress::getIntIP(const std::string &strIP) { int num = 0; for(uint i=0; i< strIP.length(); i++) if(strIP[i] == '.') num++; // check if it consists of 4 parts if(num != 3){ isValidIP = false; return 0; } // get all 4 parts in unsigned char parts[4]; int start = 0, end = 0; for(int i=0; i<4; i++){ for(uint j= start; j<strIP.length(); j++){ if(strIP[j] == '.'){ end = j; break; } if(strIP[j] < '0' || strIP[j] > '9'){ isValidIP = false; return 0; } } //printf("3 strIP:%s\n",strIP.c_str()); std::string tmp = strIP.substr(start, end - start); int tmpInt = atoi(tmp.c_str()); if(tmpInt< 0 || tmpInt > 255){ isValidIP = false; return 0; } parts[i] = (unsigned char)tmpInt; start = end + 1; } // put all 4 parts into one uint return ((uint)parts[0])<<24 | ((uint)parts[1])<<16 | ((uint)parts[2])<<8 | parts[3]; }
不错,这个工具类,自己可以随时用到。 随时拿来主义。嘎嘎
转载于:https://blog.51cto.com/no001/1317425