From 5b57c8a19ec8148b341780ea5eab0a5e90b0aeba Mon Sep 17 00:00:00 2001 From: chenzhouyu Date: Sat, 18 Feb 2017 15:32:52 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E8=BD=AC=E4=B9=89=E4=BD=BF=E7=94=A8goLang=E5=AE=98=E6=96=B9?= =?UTF-8?q?=E7=9A=84=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- qqwry.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/qqwry.go b/qqwry.go index b6bf4e6..86dc750 100644 --- a/qqwry.go +++ b/qqwry.go @@ -3,12 +3,13 @@ package main import ( "encoding/binary" "errors" - "github.com/axgle/mahonia" "io/ioutil" "log" "net" "os" "strings" + + "golang.org/x/text/encoding/simplifiedchinese" ) var IpData fileData @@ -31,7 +32,6 @@ func (f *fileData) InitIpData() (rs interface{}) { } defer f.Path.Close() - tmpData, err := ioutil.ReadAll(f.Path) if err != nil { log.Println(err) @@ -63,16 +63,16 @@ func (q *QQwry) ReadData(num int, offset ...int64) (rs []byte) { q.SetOffset(offset[0]) } nums := int64(num) - end := q.Offset+nums + end := q.Offset + nums dataNum := int64(len(q.Data.Data)) - if (q.Offset > dataNum) { + if q.Offset > dataNum { return nil } - if (end > dataNum) { + if end > dataNum { end = dataNum } - rs = q.Data.Data[q.Offset : end] + rs = q.Data.Data[q.Offset:end] q.Offset = end return } @@ -120,10 +120,9 @@ func (q *QQwry) Find(ip string) (res resultQQwry) { area = q.readArea(offset + uint32(5+len(country))) } - - enc := mahonia.NewDecoder("gbk") - res.Country = enc.ConvertString(string(country)) - res.Area = enc.ConvertString(string(area)) + enc := simplifiedchinese.GBK.NewDecoder() + res.Country, _ = enc.String(string(country)) + res.Area, _ = enc.String(string(area)) return } From 4908d142881e9954db466620e6875607212e842f Mon Sep 17 00:00:00 2001 From: chenzhouyu Date: Sat, 18 Feb 2017 16:00:35 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E7=9A=84?= =?UTF-8?q?=E8=BF=87=E6=BB=A4=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 53458ac..b75af16 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ qqwry.iml qqwry.dat qqwry qqwry_linux_amd64 + +launch.json \ No newline at end of file From 9fc90b42b4c1fda706010b2c69b5d2ad20a63529 Mon Sep 17 00:00:00 2001 From: chenzhouyu Date: Sat, 18 Feb 2017 16:00:49 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E8=A7=84=E8=8C=83=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- consts.go | 29 ++++++++++++++---------- main.go | 18 +++++++-------- qqwry.go | 64 +++++++++++++++++++++++++++-------------------------- response.go | 28 ++++++++++++----------- 4 files changed, 74 insertions(+), 65 deletions(-) diff --git a/consts.go b/consts.go index 685ce75..e88813d 100644 --- a/consts.go +++ b/consts.go @@ -1,36 +1,41 @@ package main import ( - "os" "net/http" + "os" ) const ( - INDEX_LEN = 7 // 索引长度 - REDIRECT_MODE_1 = 0x01 // 国家的类型, 指向另一个指向 - REDIRECT_MODE_2 = 0x02 // 国家的类型, 指向一个指向 + // IndexLen 索引长度 + IndexLen = 7 + // RedirectMode1 国家的类型, 指向另一个指向 + RedirectMode1 = 0x01 + // RedirectMode2 国家的类型, 指向一个指向 + RedirectMode2 = 0x02 ) -type resultQQwry struct { - Ip string `json:"ip"` +// ResultQQwry 归属地信息 +type ResultQQwry struct { + IP string `json:"ip"` Country string `json:"country"` Area string `json:"area"` } type fileData struct { - Data []byte + Data []byte FilePath string Path *os.File - IpNum int64 + IPNum int64 } +// QQwry 纯真ip库 type QQwry struct { - Data *fileData - Offset int64 + Data *fileData + Offset int64 } -// 向客户端返回数据的 -type response struct { +// Response 向客户端返回数据的 +type Response struct { r *http.Request w http.ResponseWriter } diff --git a/main.go b/main.go index 4db3528..a4109b7 100644 --- a/main.go +++ b/main.go @@ -2,12 +2,12 @@ package main import ( "flag" + "fmt" "log" "net/http" "runtime" - "time" - "fmt" "strings" + "time" ) func main() { @@ -16,20 +16,20 @@ func main() { port := flag.String("port", "2060", "HTTP 请求监听端口号") flag.Parse() - IpData.FilePath = *datFile + IPData.FilePath = *datFile startTime := time.Now().UnixNano() - res := IpData.InitIpData() + res := IPData.InitIPData() if v, ok := res.(error); ok { log.Panic(v) } endTime := time.Now().UnixNano() - log.Printf("IP 库加载完成 共加载:%d 条 IP 记录, 所花时间:%.1f ms\n", IpData.IpNum, float64(endTime-startTime)/1000000) + log.Printf("IP 库加载完成 共加载:%d 条 IP 记录, 所花时间:%.1f ms\n", IPData.IPNum, float64(endTime-startTime)/1000000) // 下面开始加载 http 相关的服务 - http.HandleFunc("/", findIp) + http.HandleFunc("/", findIP) log.Printf("开始监听网络端口:%s", *port) @@ -38,8 +38,8 @@ func main() { } } -// 查找 IP 地址的接口 -func findIp(w http.ResponseWriter, r *http.Request) { +// findIP 查找 IP 地址的接口 +func findIP(w http.ResponseWriter, r *http.Request) { res := NewResponse(w, r) ip := r.Form.Get("ip") @@ -53,7 +53,7 @@ func findIp(w http.ResponseWriter, r *http.Request) { qqWry := NewQQwry() - rs := map[string]resultQQwry{} + rs := map[string]ResultQQwry{} if len(ips) > 0 { for _, v := range ips { rs[v] = qqWry.Find(v) diff --git a/qqwry.go b/qqwry.go index 86dc750..2401978 100644 --- a/qqwry.go +++ b/qqwry.go @@ -12,10 +12,11 @@ import ( "golang.org/x/text/encoding/simplifiedchinese" ) -var IpData fileData +// IPData IP库的数据 +var IPData fileData -// 初始化ip库数据到内存中 -func (f *fileData) InitIpData() (rs interface{}) { +// InitIPData 初始化ip库数据到内存中 +func (f *fileData) InitIPData() (rs interface{}) { // 判断文件是否存在 _, err := os.Stat(f.FilePath) @@ -45,19 +46,19 @@ func (f *fileData) InitIpData() (rs interface{}) { start := binary.LittleEndian.Uint32(buf[:4]) end := binary.LittleEndian.Uint32(buf[4:]) - f.IpNum = int64((end-start)/INDEX_LEN + 1) + f.IPNum = int64((end-start)/IndexLen + 1) return true } -// 新建 qqwry 类型 +// NewQQwry 新建 qqwry 类型 func NewQQwry() QQwry { return QQwry{ - Data: &IpData, + Data: &IPData, } } -// 从文件中读取数据 +// ReadData 从文件中读取数据 func (q *QQwry) ReadData(num int, offset ...int64) (rs []byte) { if len(offset) > 0 { q.SetOffset(offset[0]) @@ -77,16 +78,17 @@ func (q *QQwry) ReadData(num int, offset ...int64) (rs []byte) { return } -// 设置偏移量 +// SetOffset 设置偏移量 func (q *QQwry) SetOffset(offset int64) { q.Offset = offset } -func (q *QQwry) Find(ip string) (res resultQQwry) { +// Find ip地址查询对应归属地信息 +func (q *QQwry) Find(ip string) (res ResultQQwry) { - res = resultQQwry{} + res = ResultQQwry{} - res.Ip = ip + res.IP = ip if strings.Count(ip, ".") != 3 { return res } @@ -99,10 +101,10 @@ func (q *QQwry) Find(ip string) (res resultQQwry) { var area []byte mode := q.readMode(offset + 4) - if mode == REDIRECT_MODE_1 { + if mode == RedirectMode1 { countryOffset := q.readUInt24() mode = q.readMode(countryOffset) - if mode == REDIRECT_MODE_2 { + if mode == RedirectMode2 { c := q.readUInt24() country = q.readString(c) countryOffset += 4 @@ -111,7 +113,7 @@ func (q *QQwry) Find(ip string) (res resultQQwry) { countryOffset += uint32(len(country) + 1) } area = q.readArea(countryOffset) - } else if mode == REDIRECT_MODE_2 { + } else if mode == RedirectMode2 { countryOffset := q.readUInt24() country = q.readString(countryOffset) area = q.readArea(offset + 8) @@ -127,26 +129,26 @@ func (q *QQwry) Find(ip string) (res resultQQwry) { return } +// readMode 获取偏移值类型 func (q *QQwry) readMode(offset uint32) byte { mode := q.ReadData(1, int64(offset)) return mode[0] } +// readArea 读取区域 func (q *QQwry) readArea(offset uint32) []byte { mode := q.readMode(offset) - if mode == REDIRECT_MODE_1 || mode == REDIRECT_MODE_2 { + if mode == RedirectMode1 || mode == RedirectMode2 { areaOffset := q.readUInt24() if areaOffset == 0 { return []byte("") - } else { - return q.readString(areaOffset) } - } else { - return q.readString(offset) + return q.readString(areaOffset) } - return []byte("") + return q.readString(offset) } +// readString 获取字符串 func (q *QQwry) readString(offset uint32) []byte { q.SetOffset(int64(offset)) data := make([]byte, 0, 30) @@ -161,29 +163,29 @@ func (q *QQwry) readString(offset uint32) []byte { return data } +// searchIndex 查找索引位置 func (q *QQwry) searchIndex(ip uint32) uint32 { header := q.ReadData(8, 0) start := binary.LittleEndian.Uint32(header[:4]) end := binary.LittleEndian.Uint32(header[4:]) - buf := make([]byte, INDEX_LEN) + buf := make([]byte, IndexLen) mid := uint32(0) _ip := uint32(0) for { mid = q.getMiddleOffset(start, end) - buf = q.ReadData(INDEX_LEN, int64(mid)) + buf = q.ReadData(IndexLen, int64(mid)) _ip = binary.LittleEndian.Uint32(buf[:4]) - if end-start == INDEX_LEN { + if end-start == IndexLen { offset := byteToUInt32(buf[4:]) - buf = q.ReadData(INDEX_LEN) + buf = q.ReadData(IndexLen) if ip < binary.LittleEndian.Uint32(buf[:4]) { return offset - } else { - return 0 } + return 0 } // 找到的比较大,向前移 @@ -194,22 +196,22 @@ func (q *QQwry) searchIndex(ip uint32) uint32 { } else if _ip == ip { return byteToUInt32(buf[4:]) } - } - return 0 } +// readUInt24 func (q *QQwry) readUInt24() uint32 { buf := q.ReadData(3) return byteToUInt32(buf) } +// getMiddleOffset func (q *QQwry) getMiddleOffset(start uint32, end uint32) uint32 { - records := ((end - start) / INDEX_LEN) >> 1 - return start + records*INDEX_LEN + records := ((end - start) / IndexLen) >> 1 + return start + records*IndexLen } -// 将 byte 转换为uint32 +// byteToUInt32 将 byte 转换为uint32 func byteToUInt32(data []byte) uint32 { i := uint32(data[0]) & 0xff i |= (uint32(data[1]) << 8) & 0xff00 diff --git a/response.go b/response.go index a763d32..cb0ace4 100644 --- a/response.go +++ b/response.go @@ -1,35 +1,37 @@ package main import ( + "fmt" "net/http" + "github.com/pquerna/ffjson/ffjson" - "fmt" ) -func NewResponse(w http.ResponseWriter, r *http.Request) response { +// NewResponse 创建一个新的response对象 +func NewResponse(w http.ResponseWriter, r *http.Request) Response { r.ParseForm() - return response{ + return Response{ w: w, r: r, } } -// 返回正确的信息 -func (r *response) ReturnSuccess(data interface{}) { +// ReturnSuccess 返回正确的信息 +func (r *Response) ReturnSuccess(data interface{}) { r.Return(data, 200) } -// 返回错误信息 -func (r *response) ReturnError(statuscode, code int, errMsg string) { - r.Return(map[string]interface{}{"errcode":code, "errmsg":errMsg}, statuscode) +// ReturnError 返回错误信息 +func (r *Response) ReturnError(statuscode, code int, errMsg string) { + r.Return(map[string]interface{}{"errcode": code, "errmsg": errMsg}, statuscode) } -// 向客户返回回数据 -func (r *response) Return(data interface{}, code int) { +// Return 向客户返回回数据 +func (r *Response) Return(data interface{}, code int) { jsonp := r.IsJSONP() rs, err := ffjson.Marshal(data) - if err != nil { + if err != nil { code = 500 rs = []byte(fmt.Sprintf(`{"errcode":500, "errmsg":"%s"}`, err.Error())) } @@ -44,8 +46,8 @@ func (r *response) Return(data interface{}, code int) { } } -// 是否为jsonp 请求 -func (r *response) IsJSONP() string { +// IsJSONP 是否为jsonp 请求 +func (r *Response) IsJSONP() string { if r.r.Form.Get("callback") != "" { return r.r.Form.Get("callback") }