You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
goip/ip2region/qqery.go

74 lines
1.7 KiB

2 years ago
package ip2region
import (
"errors"
"net"
"strconv"
)
type QueryResult struct {
Ip string `json:"ip,omitempty"` // ip
CityId int64 `json:"city_id,omitempty"` // 城市代码
Country string `json:"country,omitempty"` // 国家
Region string `json:"region,omitempty"` // 区域
Province string `json:"province,omitempty"` // 省份
City string `json:"city,omitempty"` // 城市
Isp string `json:"isp,omitempty"` // 运营商
}
func (ip QueryResult) String() string {
return ip.Ip + "|" + strconv.FormatInt(ip.CityId, 10) + "|" + ip.Country + "|" + ip.Region + "|" + ip.Province + "|" + ip.City + "|" + ip.Isp
}
// Query memory算法整个数据库全部载入内存单次查询都在0.1x毫秒内
func (c *Client) Query(ipAddress net.IP) (result QueryResult, err error) {
result.Ip = ipAddress.String()
if c.totalBlocks == 0 {
if err != nil {
2 years ago
return QueryResult{}, err
2 years ago
}
c.firstIndexPtr = getLong(dbBuff, 0)
c.lastIndexPtr = getLong(dbBuff, 4)
c.totalBlocks = (c.lastIndexPtr-c.firstIndexPtr)/IndexBlockLength + 1
}
ip, err := ip2long(result.Ip)
if err != nil {
2 years ago
return QueryResult{}, err
2 years ago
}
h := c.totalBlocks
var dataPtr, l int64
for l <= h {
m := (l + h) >> 1
p := c.firstIndexPtr + m*IndexBlockLength
sip := getLong(dbBuff, p)
if ip < sip {
h = m - 1
} else {
eip := getLong(dbBuff, p+4)
if ip > eip {
l = m + 1
} else {
dataPtr = getLong(dbBuff, p+8)
break
}
}
}
if dataPtr == 0 {
2 years ago
return QueryResult{}, errors.New("not found")
2 years ago
}
dataLen := (dataPtr >> 24) & 0xFF
dataPtr = dataPtr & 0x00FFFFFF
result = getIpInfo(result.Ip, getLong(dbBuff, dataPtr), dbBuff[(dataPtr)+4:dataPtr+dataLen])
2 years ago
return result, nil
2 years ago
}