golang解析IP到城市jsonRPC服務

jjjjerk發表於2018-03-13

RESTful介面

請求URL:

  • https://api.turboes.com/Tbsapi/v1/ip2addr?ip=219.140.227.235

請求方式:

  • GET

引數:

引數名 型別 說明
ip url-qurey-string 可選 要查詢的ip地址,如果不傳這表示當前的ip

返回示例

{
    "code": 1,
    "data": {
        "Country": "中國",
        "Province": "湖北省",
        "City": "武漢",
        "ISP": "",
        "Latitude": 30.5801,
        "Longitude": 114.2734,
        "TimeZone": "Asia/Shanghai"
    },
    "ip": "219.140.227.235"
}

json_rpc tcp 地址: 121.40.238.123(IP地址更快) api.turboes.com 埠: 3344


第三方資源

go標準庫jsonRPC服務端

Go官方提供了一個RPC庫: net/rpc。包rpc提供了通過網路訪問一個物件的方法的能力。伺服器需要註冊物件, 通過物件的型別名暴露這個服務。註冊後這個物件的輸出方法就可以遠端呼叫,這個庫封裝了底層傳輸的細節,包括序列化。伺服器可以註冊多個不同型別的物件,但是註冊相同型別的多個物件的時候回出錯。

  • 方法的型別是可輸出的 (the method's type is exported)
  • 方法本身也是可輸出的 (the method is exported)
  • 方法必須由兩個引數,必須是輸出型別或者是內建型別 (the method has two arguments, both exported or builtin types)
  • 方法的第二個引數是指標型別 (the method's second argument is a pointer)
  • 方法返回型別為 error (the method has return type error)
package main

import (
    "fmt"
    "github.com/oschwald/geoip2-golang"
    "net"
    "net/rpc"
    "net/rpc/jsonrpc"
    "os"
    "log"
)
//返回值結構體
//需要滿足以上要求
type Response struct {
    Country   string
    Province  string
    City      string
    ISP       string
    Latitude  float64
    Longitude float64
    TimeZone  string
}

type Ip2addr struct {
    db *geoip2.Reader
}
//引數結構體
//需要滿足以上要求
type Agrs struct {
    IpString string
}
//json rpc 處理請求
//需要滿足以上要求
func (t *Ip2addr) Address(agr *Agrs, res *Response) error {
    netIp := net.ParseIP(agr.IpString)
        //呼叫開源geoIp 資料庫查詢ip地址
    record, err := t.db.City(netIp)
    res.City = record.City.Names["zh-CN"]
    res.Province = record.Subdivisions[0].Names["zh-CN"]
    res.Country = record.Country.Names["zh-CN"]
    res.Latitude = record.Location.Latitude
    res.Longitude = record.Location.Longitude
    res.TimeZone = record.Location.TimeZone
    return err
}

func main() {
         //載入geoIp資料庫
    db, err := geoip2.Open("./GeoLite2-City.mmdb")
    if err != nil {
        log.Fatal(err)
    }
        //初始化jsonRPC
    ip2addr := &Ip2addr{db}
       //註冊
    rpc.Register(ip2addr)
       //繫結埠
    address := ":3344"
    tcpAddr, err := net.ResolveTCPAddr("tcp", address)
    checkError(err)
    listener, err := net.ListenTCP("tcp", tcpAddr)
    checkError(err)
    log.Println("json rpc is listening",tcpAddr)
    for {
        conn, err := listener.Accept()
        if err != nil {
            continue
        }
        jsonrpc.ServeConn(conn)
    }

}

func checkError(err error) {
    if err != nil {
        fmt.Println("Fatal error ", err.Error())
        os.Exit(1)
    }
}

PHP-jsonRPC客戶端


class JsonRPC
{
    public $conn;

    function __construct($host, $port)
    {
        $this->conn = fsockopen($host, $port, $errno, $errstr, 3);
        if (!$this->conn) {
            return false;
        }
    }

    public function Call($method, $params)
    {
        $obj = new stdClass();
        $obj->code = 0;

        if (!$this->conn) {
            $obj->info = "jsonRPC連線失敗!";
            return $obj;
        }
        $err = fwrite($this->conn, json_encode(array(
                'method' => $method,
                'params' => array($params),
                'id' => 0,
            )) . "\n");
        if ($err === false) {
            fclose($this->conn);
            $obj->info = "jsonRPC傳送引數失敗!請檢查自己的rpc-client程式碼";
            return $obj;
        }

        stream_set_timeout($this->conn, 0, 3000);
        $line = fgets($this->conn);
        fclose($this->conn);
        if ($line === false) {
            $obj->info = "jsonRPC返回訊息為空!請檢查自己的rpc-client程式碼";
            return $obj;
        }
        $temp = json_decode($line);
        $obj->code = $temp->error == null ? 1 : 0;
        $obj->data = $temp->result;
        return $obj;
    }
}

function json_rpc_ip_address($ipString)
{
    $client = new JsonRPC("127.0.0.1", 3344);
    $obj = $client->Call("Ip2addr.Address", ['IpString' => $ipString]);
    return $obj;
}

go語言jsonRPC客戶端

package main

import (
    "fmt"
    "log"
    "net/rpc/jsonrpc"
)

type Response struct {
    Country   string
    Province  string
    City      string
    ISP       string
    Latitude  float64
    Longitude float64
    TimeZone  string
}
type Agrs struct {
    IpString string
}
func main() {
    client, err := jsonrpc.Dial("tcp", "121.40.238.123:3344")
    if err != nil {
        log.Fatal("dialing:", err)
    }
    // Synchronous call
    var res Response
    err = client.Call("Ip2addr.Address", Agrs{"219.140.227.235"}, &res)
    if err != nil {
        log.Fatal("ip2addr error:", err)
    }
    fmt.Println(res)

}

程式碼地址

歡迎pr/star golang-captcha

相關文章