First look at the content structure of the Qqwry.data file and how it is interpreted.
I. Structure of documents
The document is divided into three main structures
1, file header, 8 bytes;
2, the data record area, indefinite length;
3, the index area, the length is 7 integer times;
Second, the document head
The 8 bytes of the header are divided into two parts, each 4 byte, specifying the start and end addresses of the index area, respectively. So you can calculate the total number of records by using the difference of two addresses, except 7 plus 1.
Ii. Record Area
The data of the record area needs to obtain the starting position of each data through the data of the index area; This area data records the end address and the region string of the IP address; All region strings end with 0x00.
Iii. Index Area
The key to retrieving IP-corresponding regions is to find the index content corresponding to the IP start address. One IP index data contains 7 bytes, the first 4 bytes are the IP address start value, the latter 3 bytes are the corresponding IP data records in the file offset address, in the IP data record, the first 4 bytes are IP end addresses, followed by two modes of data: 0x01 mode and 0x02 mode.
The 0x01 mode, where the 5th byte of the IP data is 0x01, is the offset address of the national region data in the following 3 bytes, and the country and region data include the two strings. That
—————————————————————
4 bytes | 3 byte redirect 0x nn nn-> country area data file offset address
—————————————————————
The 0x02 mode, in which the 5th byte of the IP data is 0x02, then the 3 bytes in the back are the offset address of the country data, and the region data is followed by a string to 0x00 up. That
—————————————————————————–
4 bytes | 3 byte redirect 0x nn nn over nn-> file offset address of the country data | Region String | 0x00
—————————————————————————–
For the 0x01 model, it is possible to have a redirected structure in the national area data, namely
————————————–
Country String | 0x00 | Region String | 0x00
————————————–
Or
————————————————————————-
Country String | 0x00 | 0x02 | 3 bytes 0x nn nn, nn-> region string file offset address
————————————————————————-
For the former case, it is simpler to read two string data directly, and in the latter case, you need to redirect to the offset address of the region string again, and then read to 0x00 for the end of the string.
The primary purpose of this method of taking the actual string value of an address map is to avoid duplicate record string values. There are too many identical string records in the entire IP address library file, and using a 3-byte mapping address is much more space-saving than a duplicate-record string value.
PHP code read operation QQWry.dat file:
The code is as follows |
Copy Code |
function Bin2ip ($bin) { $ip = '; $BD = Str_split ($bin, 1); for ($i = 4; $i > 0; $i-) { $ip. = ".". sprintf ("%03d", implode (', unpack (' s ', $bd [$i-1]. chr (0))); } Return substr ($IP, 1); } //-------------------------------------------------- $f = fopen (' QQWry.Dat ', ' R '); $c = Fread ($f, 4); $d = Fread ($f, 4); $index _begin = Implode (', Unpack (' L ', $c)); $index _end = Implode (', Unpack (' L ', $d)); if ($index _begin < 0) $index _begin + = POW (2, 32); if ($index _end < 0) $index _end + = POW (2, 32); $ip _num = ($index _end-$index _begin)/7 + 1; echo "index begin at: $index _beginn"; echo "Index end at: $index _endn"; echo "IP data count: $ip _numn"; $output = '; for ($i = 0; $i < $ip _num; $i + +) { The file pointer refers to the index data (7 bytes) of each IP data file. Fseek ($f, $i * 7 + $index _begin); $ip 4 = fread ($f, 4); IP Start Address if (strlen ($ip 4) < 4) exit (' Data file error '); $ip 3 = fread ($f, 3); IP Record offset Address if (strlen ($ip 3) < 3) exit (' Data file error '); $dataseek = Implode (', Unpack (' L ', $ip 3 chr (0))); if ($dataseek < 0) $index _ip_record + = POW (2, 32); Find records $dataseek location in the record area Fseek ($f, $dataseek); $ipdata = Fread ($f, 4); IP End Address if (strlen ($ipdata) < 4) exit (' Data file error '); $area = '; $country = '; Read a marker bit $flag = Fread ($f, 1); if ($flag = = Chr (1)) {//Country name offset Mark bit mode 0x01 $area 1seek = Fread ($f, 3); if (strlen ($area 1seek) < 3) exit (' Data file error '); $area 1seek = Implode (', Unpack (' L ', $area 1seek. chr (0))); Fseek ($f, $area 1seek); $flag = Fread ($f, 1); Might be a marker again. } if ($flag = = Chr (2)) {//Country area redirect $area 1seek = Fread ($f, 3); if (strlen ($area 1seek) < 3) exit (' Data file error '); $area 1seek = Implode (', Unpack (' L ', $area 1seek. chr (0))); $flag = Fread ($f, 1); if ($flag = = Chr (2)) { $area 2seek = Fread ($f, 3); $area 2seek = Implode (', Unpack (' L ', $area 2seek. chr (0))); Fseek ($f, $area 2seek); }else{ Fseek ($f,-1, seek_cur); } while ($c = Fread ($f, 1))!= chr (0)) $area. = $c; Fseek ($f, $area 1seek); while ($c = Fread ($f, 1))!= chr (0)) $country. = $c; }else{ Fseek ($f,-1, seek_cur); while ($c = Fread ($f, 1))!= chr (0)) $country. = $c; $flag = Fread ($f, 1); If the region is redirected if ($flag = = Chr (2)) { $area 2seek = Fread ($f, 3); $area 2seek = Implode (', Unpack (' L ', $area 2seek. chr (0))); Fseek ($f, $area 2seek); }else{ Fseek ($f,-1, seek_cur); } while ($c = Fread ($f, 1))!= chr (0)) $area. = $c; } $adata = Trim ($country). Trim ($area); $country is a country string, $area is a region string } Fclose ($f); |
This function we see most is the file operation related functions such as fopen,fseek,fread these, the need for friends to see.