欢迎光临
我们一直在努力

go语言学习例子No.30–页面实时获取系统信息7

golang的json结构体转换

https://mholt.github.io/json-to-go/

添加了多用户,基本的功能已经实现,应该只能在ubuntu和debian系统下才能运行,因为我只会用这两个系统

效果如下

知识点有点杂,我都不知道怎么总结

index.html部分

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <title>VPS云监控 by foxzc</title>

    <!-- Bootstrap core CSS -->
<link href="assets/dist/css/bootstrap.min.css" rel="stylesheet">
    
  </head>
  <body>
  <div class="container themed-container">
      <header class="d-flex justify-content-center py-3">
        <p class="h2">系统信息</p>
      </header>
        <table class="table table-sm table-bordered" style="text-align: center;">
          <thead>
          <tr>
            <th scope="col">节点名</th>
            <th scope="col">在线时间</th>
            <th scope="col">网络 ↓|↑</th>
            <th scope="col">流量 ↓|↑</th>
            <th scope="col">处理器</th>
            <th scope="col">内存</th>
            <th scope="col">硬盘</th>
          </tr>
          </thead>
          <tbody id="servers">
            <!-- Servers here \o/ -->
          </tbody>
        </table>
    </article>
  </div>

    <script src="assets/dist/js/bootstrap.bundle.min.js"></script>
  <script src="assets/dist/js/jquery-3.6.0.min.js"></script>
    <script src="assets/dist/js/loli.js"></script>


  </body>
</html>

js部分

$(function (){
    firstajax();
    function firstajax(){
        $.get('/ajax',function(data,status){
            if (status == 'success') {
                $("#servers tr").remove();
            for (var i = 0 ; i < data.servers.length; i++) {
                $("#servers").append(`<tr id="r`+i+`" data-bs-toggle="collapse" data-bs-target="#tr`+i+`" aria-expanded="true">
            <th id="name">Name</th>
            <td id="day">0天</td>
            <td id="net">1K | 1K</td>
            <td id="speed">1G | 1G</td>
            <td><div class="progress">
              <div class="progress-bar bg-success" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" id="cpu">0%</div></div></td>
            <td><div class="progress">
              <div class="progress-bar bg-success" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" id="mem">0%</div></div></td>
            <td><div class="progress">
              <div class="progress-bar bg-success" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" id="disk">0%</div></div></td>
          </tr>
          <tr>
            <td colspan="16"><div id="tr`+i+`" class="collapse">
              显示额外信息
            </div></td>
            
          </tr>`)
                   
                }
                for (var i = 0; i < data.servers.length; i++) {
                    cpuclass = data.servers[i].Cpuused+"%"
                    memclass = data.servers[i].Memused+"%"
                    diskclass = data.servers[i].Diskused+"%"
                    $('#r'+i+' #name').text(data.servers[i].Name)
                    $('#r'+i+' #cpu').css("width",cpuclass)
                    $('#r'+i+' #cpu').text(data.servers[i].Cpuused+"%")
                    $('#r'+i+' #mem').css("width",memclass)
                    $('#r'+i+' #mem').text(data.servers[i].Memused+"%")
                    $('#r'+i+' #disk').css("width",diskclass)
                    $('#r'+i+' #disk').text(data.servers[i].Diskused+"%")
                    $('#r'+i+' #net').text(data.servers[i].Netsend+"G | "+data.servers[i].Netrecv+"G")
                    $('#r'+i+' #speed').text(data.servers[i].Netdown+" | "+data.servers[i].Netup)
                    $('#r'+i+' #day').text(data.servers[i].Uptime+"天")
                    $('#tr'+i).text("硬盘: "+data.servers[i].Diskfree+"G/"+ data.servers[i].Disktotal+'G | 内存: '+data.servers[i].Memavailable+"G/"+ data.servers[i].Memtotal+"G | Swap: "+data.servers[i].Swapfree+"G/"+data.servers[i].Swaptotal+"G")
                }

            }
                
        });
    };
    setInterval(myajax, 2000);
    function myajax(){
        $.get('/ajax',function(data,status){
            if (status == 'success') {
                for (var i = 0; i < data.servers.length; i++) {
                    cpuclass = data.servers[i].Cpuused+"%"
                    memclass = data.servers[i].Memused+"%"
                    diskclass = data.servers[i].Diskused+"%"
                    $('#r'+i+' #name').text(data.servers[i].Name)
                    $('#r'+i+' #cpu').css("width",cpuclass)
                    $('#r'+i+' #cpu').text(data.servers[i].Cpuused+"%")
                    $('#r'+i+' #mem').css("width",memclass)
                    $('#r'+i+' #mem').text(data.servers[i].Memused+"%")
                    $('#r'+i+' #disk').css("width",diskclass)
                    $('#r'+i+' #disk').text(data.servers[i].Diskused+"%")
                    $('#r'+i+' #net').text(data.servers[i].Netsend+"G | "+data.servers[i].Netrecv+"G")
                    $('#r'+i+' #speed').text(data.servers[i].Netdown+" | "+data.servers[i].Netup)
                    $('#r'+i+' #day').text(data.servers[i].Uptime+"天")
                    $('#tr'+i).text("硬盘: "+data.servers[i].Diskfree+"G/"+ data.servers[i].Disktotal+'G | 内存: '+data.servers[i].Memavailable+"G/"+ data.servers[i].Memtotal+"G | Swap: "+data.servers[i].Swapfree+"G/"+data.servers[i].Swaptotal+"G")
                }

            }
                
        });
    };
});

服务端部分

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"text/template"
)

//定义json配置文件解析后的结构
type ClientJson struct {
	Servers []struct {
		Username string `json:"username"`
		Password string `json:"password"`
		Name     string `json:"name"`
	} `json:"servers"`
}
//定义传出的json配置文件解析后的结构
type Clients struct {
	 Servers []Server`json:"servers"`

}
type Server struct {
Name         string
Cpuused      int     `json:"Cpuused"`
Memused      int     `json:"Memused"`
Memavailable float64 `json:"Memavailable"`
Swaptotal    float64 `json:"Swaptotal"`
Swapfree     float64 `json:"Swapfree"`
Memtotal     float64 `json:"Memtotal"`
Disktotal    float64 `json:"Disktotal"`
Diskfree     float64 `json:"Diskfree"`
Diskused     int     `json:"Diskused"`
Netsend      float64 `json:"Netsend"`
Netrecv      float64 `json:"Netrecv"`
Netup        string  `json:"Netup"`
Netdown      string  `json:"Netdown"`
Uptime       int     `json:"Uptime"`
}

func index(w http.ResponseWriter, r *http.Request) {
	t, _ := template.ParseFiles("index.html") //找模板
	t.Execute(w, nil)                         //执行模板
}
func ajax(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-type", "application/json;charset=utf-8")
}
func main() {
	clientjson := ClientJson{}
	clients :=Clients{}
	//下面使用的是相对路径,config.json文件和main.go文件处于同一目录下
	Readjson("./config.json", &clientjson)
	clients.Servers=make([]Server,len(clientjson.Servers))//读取了配置文件,配置文件里有几个用户就make几个
	Setname(clientjson,clients.Servers)
	go startserver(clientjson,clients)//开个协程,要不然会跟http的监听有冲突
	http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets"))))
	http.HandleFunc("/", index)      //函数也是一种变量
	http.HandleFunc("/ajax", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-type", "application/json;charset=utf-8")
		d,_:=json.Marshal(clients)
		fmt.Fprintln(w,string(d))
	}) //函数也是一种变量
	http.ListenAndServe(":8082", nil)
}



func startserver(clientjson ClientJson,clients Clients){
	addr, _ := net.ResolveTCPAddr("tcp4", "0.0.0.0:8899")
	lis, _ := net.ListenTCP("tcp4", addr)
	fmt.Println("服务器已启动")

	for {//通过gorountine,每个客户端分配一个独立协程。
		conn, _ := lis.Accept()
		go handleConn(conn,clientjson,clients)
	}

	fmt.Println("服务器结束")
}

func handleConn(conn net.Conn,clientjson ClientJson,clients Clients){
	defer conn.Close()
	b := make([]byte, 256)
	count, err := conn.Read(b)//接收第一个传过来的账号和密码
	if err != nil {//这里判断一下err,如果断开就跳出循环,关闭当前连接
		fmt.Println("客户端断开连接")
		return
	}
	arr := strings.Split(string(b[:count]),":")//验证账号和密码
	isbool,k:=Confirm(arr[0],arr[1],clientjson,clients)
	if !isbool{
		fmt.Println("用户名或者密码错误!")
		return
	}
	for{//验证通过了,就一直保持连接接收信息
		count, err := conn.Read(b)
		if err != nil {//这里判断一下err,如果断开就跳出循环,关闭当前连接
			fmt.Println(arr[0]+"客户端断开连接")
			break
		}
		err=json.Unmarshal(b[:count],&clients.Servers[k])
		if err != nil {//这里判断一下err,如果断开就跳出循环,关闭当前连接
			fmt.Println(err.Error())
			break
		}
	}
}

func Readjson(filename string, v interface{}) {
	//ReadFile函数会读取文件的全部内容,并将结果以[]byte类型返回
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}
	//读取的数据为json格式,需要进行解码
	err = json.Unmarshal(data, v)
	if err != nil {
		return
	}
}

func Confirm(u string,pd string,clientjson ClientJson,clients Clients) (bool,int){
	for k,v := range clientjson.Servers {
		if v.Username == u && v.Password == pd{
			fmt.Println(v.Username+"登录成功!")
			clients.Servers[k].Name=v.Name
			return true,k
		}
	}
	return false,0
}
func Setname(clientjson ClientJson,clients []Server){
	for k, v := range clientjson.Servers {
		clients[k].Name=v.Name
		}
}

客户端部分

package main

import (
	"encoding/json"
	"fmt"
	net2 "net"
	"strconv"
	"strings"
	"time"
	"os"

	"github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/disk"
	"github.com/shirou/gopsutil/host"
	"github.com/shirou/gopsutil/mem"
	"github.com/shirou/gopsutil/net"
)

type Sys struct {
	Cpuused      int
	Memused      int
	Memavailable float64
	Swaptotal    float64
	Swapfree     float64
	Memtotal     float64
	Disktotal    float64
	Diskfree     float64
	Diskused     int
	Netsend      float64
	Netrecv      float64
	Netup        string
	Netdown      string
	Uptime       int
}

func main() {
	username:=os.Args[1]
	pwd:=os.Args[2]
	addr:= os.Args[3]
	if username=="" || pwd=="" || addr=="" {
		fmt.Println("输入的参数有误!例如: ./main username password 127.0.0.1:8899")
	}
	//服务器端ip和端口
	conn, err := net2.Dial("tcp4", addr)
	if err != nil {
		fmt.Println(err.Error())
	}
	//向服务端发送数据
	s := Sys{}
	c := make(chan []byte, 2) //设置2个缓存,这样取了一个就会马上放进去一个
	go func() {
		for {
			s = getstatus()
			d, _ := json.Marshal(s)
			c <- d
		}
	}()
	_, err = conn.Write([]byte(username+":"+pwd)) //发送账号密码
	if err != nil {                                  //如果验证不通过就结束程序
		fmt.Println(err.Error())
		return
	}
	for {
		_, err := conn.Write(<-c)
		if err != nil {
			fmt.Println(err.Error())
			break
		}
	}
	////关闭连接
	defer conn.Close()
}
func toG(i uint64) float64 {
	return float64(i) / 1024 / 1024 / 1024
}
func toKB(i uint64) float64 {
	return float64(i) / 1024
}
func toMB(i uint64) float64 {
	return float64(i) / 1024 / 1024
}
func Decimal(value float64) float64 {
	value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
	return value
}

func getNetSpeed() (string, string) {
	// 读取所有网卡网速
	Net, _ := net.IOCounters(true)
	// 定义网速保存变量
	var rx, tx uint64
	// 循环网络信息
	for _, nv := range Net {
		// 去除多余信息
		if strings.Contains(nv.Name, "eth") || strings.Contains(nv.Name, "ens") {
			// 加上网速信息
			rx += nv.BytesRecv
			tx += nv.BytesSent
		}
	}
	// 暂停一秒
	time.Sleep(time.Second)
	// 重新读取网络信息
	Net, _ = net.IOCounters(true)
	// 网络信息保存变量
	var rx2, tx2 uint64
	// 循环网络信息
	for _, nv := range Net {
		// 去除多余信息
		if strings.Contains(nv.Name, "eth") || strings.Contains(nv.Name, "ens") {
			// 加上网速信息
			rx2 += nv.BytesRecv
			tx2 += nv.BytesSent
		}
	}
	// 两次相减
	if toKB(rx2-rx) > 1024 || toKB(tx2-tx) > 1024 {
		down := strconv.FormatFloat(toMB(rx2-rx), 'f', 2, 64) + "MB/S"
		up := strconv.FormatFloat(toMB(tx2-tx), 'f', 2, 64) + "MB/S"
		return down, up
	} else {
		down := strconv.FormatFloat(toKB(rx2-rx), 'f', 2, 64) + "KB/S"
		up := strconv.FormatFloat(toKB(tx2-tx), 'f', 2, 64) + "KB/S"
		return down, up
	}

}
func getstatus() Sys {
	s := Sys{}
	m, _ := mem.VirtualMemory()
	c, _ := cpu.Percent(time.Second, false)
	d, _ := disk.Usage("/")
	n, _ := net.IOCounters(true)
	swap, _ := mem.SwapMemory()
	s.Netsend = Decimal(toG(n[1].BytesSent))
	s.Netrecv = Decimal(toG(n[1].BytesRecv))
	s.Diskused = int(d.UsedPercent)
	s.Diskfree = Decimal(toG(d.Free))
	s.Disktotal = Decimal(toG(d.Total))
	s.Memused = int(m.UsedPercent)
	s.Memtotal = Decimal(toG(m.Total))
	s.Memavailable = Decimal(toG(m.Available))
	s.Cpuused = int(c[0])
	s.Netdown, s.Netup = getNetSpeed()
	s.Uptime = int(getUptime() / 60 / 60 / 24)
	s.Swaptotal = Decimal(toG(swap.Total))
	s.Swapfree = Decimal(toG((swap.Free)))
	return s
}
func getUptime() uint64 { //获取的是秒数
	up, err := host.BootTime()
	if nil != err {
		return 0
	}
	return uint64(time.Now().Unix()) - up
}

服务端这么运行

go run main.go username password 127.0.0.1:8899

代码应该还可以优化一下,比如用结构体的方法什么的,本人新手,完全就是函数堆起来的,感觉很麻烦

 收藏 (0) 打赏

您可以选择一种方式赞助本站

支付宝扫一扫赞助

微信钱包扫描赞助

未经允许不得转载:家里蹲的狐狸 » go语言学习例子No.30–页面实时获取系统信息7

分享到: 生成海报
avatar

评论 抢沙发

  • QQ号
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

登录

忘记密码 ?

切换登录

注册

我们将发送一封验证邮件至你的邮箱, 请正确填写以完成账号注册和激活