Server
package main
import (
"fmt"
"net/http"
// _ "net/http/pprof"
"github.com/gin-gonic/gin"
)
func main() {
gin.SetMode(gin.ReleaseMode)
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
if c.Request.Header["User-Agent"][0] != "windows" {
fmt.Println("请求头错误")
c.JSON(http.StatusBadRequest, gin.H{})
} else {
reqIP := c.ClientIP()
c.JSON(200, gin.H{
"message": reqIP,
})
}
})
// go http.ListenAndServe("0.0.0.0:9999", nil)
r.Run("0.0.0.0:56789")
}
Systemd 管理
vim /usr/lib/systemd/system/returnip.service
[Unit]
Description=Return IP Address
[Service]
Type=simple
Restart=always
RestartSec=5s
ExecStart=/usr/local/go-bin/returnIP
WorkingDirectory=/usr/local/go-bin
[Install]
WantedBy=multi-user.target
开启 pprof
pprof是Go的性能分析工具,在程序运行过程中,可以记录程序的运行信息,可以是CPU使用情况、内存使用情况、goroutine运行情况等,当需要性能调优或者定位Bug时候,这些记录的信息是相当重要。
去掉代码中注释
// _ "net/http/pprof"
// go http.ListenAndServe("0.0.0.0:9999", nil)
访问如下地址:
http://server:9999/debug/pprof/
Client
package main
import (
"encoding/json"
"io"
"log"
"net"
"net/http"
"time"
"github.com/robfig/cron/v3"
)
var ip string
func main() {
// 运行次数
num := 0
// 设置时区
local, err := time.LoadLocation("Asia/Shanghai")
// Windows server 2022 服务器无法使用上面代码初始化时区
// 使用下面代码初始化时区
if err != nil {
log.Println("初始化时区错误: ", err.Error())
local = time.FixedZone("CST", 8*3600)
}
interval := cron.New(cron.WithLocation(local), cron.WithSeconds()) // 设置时区并且精度按秒。
// timeout示例,写法v1的相同:
// 每12s运行一次:"@every 12s" 或 "*/12 * * * * *"
// 每分钟的第0s执行一次:"0 */1 * * * *"
timeout := "*/10 * * * * *"
// intervalId, err := interval.AddFunc(timeout, func() {
// num++
// log.Println("全局定时器已开启=num=", num)
// })
intervalId, err := interval.AddFunc(timeout, httpRequest)
if err != nil {
log.Println("全局定时器报错", "\n error=", err, "\n num=", num)
return
}
log.Println("全局定时器已开启,Id=", intervalId)
interval.Start()
//关闭着计划任务, 但是不能关闭已经在执行中的任务.
defer interval.Stop()
select {} // 阻塞主线程而不退出
}
func httpRequest() {
url := "http://server:56789/ping"
request, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Panicln(err.Error())
}
// 设置请求投
request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
request.Header.Add("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3")
request.Header.Add("Connection", "keep-alive")
// request.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36")
request.Header.Add("User-Agent", "windows")
client := http.Client{}
// Do sends an HTTP request and returns an HTTP response
// 发起一个HTTP请求,返回一个HTTP响应
resp, err := client.Do(request)
if resp.StatusCode != http.StatusOK {
log.Println("访问错误")
return
}
if err != nil {
// log.Panicln("请求错误")
log.Println("请求错误")
return
}
// 关闭 resp,避免内存泄漏
defer resp.Body.Close()
var result struct {
Message string `json:"message"`
}
body, err := io.ReadAll(resp.Body)
if err != nil {
// log.Panicln("返回结果错误")
log.Println("返回结果错误")
return
}
err = json.Unmarshal(body, &result)
if err != nil {
// log.Panicln("IP 序列化错误")
log.Println("IP 序列化错误")
return
}
tmpIP := result.Message
address := net.ParseIP(tmpIP)
if address == nil {
// log.Panicln("IP 地址不合法")
log.Println("IP 地址不合法")
return
} else {
if tmpIP != ip {
ip = result.Message
log.Println("IP 已经改变:", result.Message)
} else {
return
}
}
}