获取公网IP的方法其实很简单,最简单的就是利用dnspod的服务,echo `nc ns1.dnspod.net 6666`,立刻就出来了。于是hugozhu的一段代码就是这样写的:
XML/HTML代码
- func GetLocalPublicIpUseDnspod() (string, error) {
 - timeout := time.Nanosecond * 30
 - conn, err := net.DialTimeout("tcp", "ns1.dnspod.net:6666", timeout*time.Second)
 - defer func() {
 - if x := recover(); x != nil {
 - log.Println("Can't get public ip", x)
 - }
 - if conn != nil {
 - conn.Close()
 - }
 - }()
 - if err == nil {
 - var bytes []byte
 - deadline := time.Now().Add(timeout * time.Second)
 - err = conn.SetDeadline(deadline)
 - if err != nil {
 - return "", err
 - }
 - bytes, err = ioutil.ReadAll(conn)
 - if err == nil {
 - return string(bytes), nil
 - }
 - }
 - return "", err
 - }
 
上面的原始代码在:http://hugozhu.myalert.info/2013/02/26/dynamic-dns-script.html,原文的代码中其实是不能运行的。因为:timeout是个未定义的变量。
OK,不说这个。我在现实中不能使用上面的代码,因为nc ns1.dnspod.net取出来的结果不正确。为什么?因为我用的是铁通,好象会经过一层代理。但是我访问ip138又是可以取到真实的公网IP,所以我使用了如下代码 :
XML/HTML代码
- func GetLocalPublicIp() (string, error) {
 - // `nc ns1.dnspod.cn 6666`
 - res, err := http.Get("http://iframe.ip138.com/ic.asp")
 - if err != nil {
 - return "", err
 - }
 - defer res.Body.Close()
 - result, err := ioutil.ReadAll(res.Body)
 - if err != nil {
 - return "", err
 - }
 - reg := regexp.MustCompile(`\d+\.\d+\.\d+\.\d+`)
 - return reg.FindString(string(result)), nil
 - }
 
上面我用的正则十分简单。就这样写写算了。因为这个页面里就这么一个符合的地方。OK,现在就一切正常了

