改下了服务端的代码,结构体改了名字,再用继承和结构体的方法来实现
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net"
"net/http"
"strings"
"text/template"
)
//定义json配置文件解析后的结构
type Config struct {
File []struct {
Username string `json:"username"`
Password string `json:"password"`
Name string `json:"name"`
} `json:"servers"`
Clients //继承下面的结构体
}
//定义传出的json配置文件解析后的结构
type Clients struct {
Infos []Info`json:"servers"`
}
type Info 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 (config *Config) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-type", "application/json;charset=utf-8")
d,_:=json.Marshal(config.Clients)
fmt.Fprintln(w,string(d))
}
func main() {
config := &Config{}
//下面使用的是相对路径,config.json文件和main.go文件处于同一目录下
Readjson("./config.json", config)
config.Clients.Infos=make([]Info,len(config.File))//读取了配置文件,配置文件里有几个用户就make几个
config.Setname(config.Clients.Infos)
go config.startserver()//开个协程,要不然会跟http的监听有冲突
http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets"))))
http.HandleFunc("/", index) //函数也是一种变量
http.Handle("/ajax",config)//这里可以绑定Config结构体,因为实现了Handler接口
http.ListenAndServe(":8082", nil)
}
func (config *Config) startserver(){
addr, _ := net.ResolveTCPAddr("tcp4", "0.0.0.0:8899")
lis, _ := net.ListenTCP("tcp4", addr)
fmt.Println("服务器已启动")
for {//通过gorountine,每个客户端分配一个独立协程。
conn, _ := lis.Accept()
go config.handleConn(conn)
}
fmt.Println("服务器结束")
}
func (config *Config) handleConn(conn net.Conn){
defer conn.Close()
b := make([]byte, 256)
count, err := conn.Read(b)//接收第一个传过来的账号和密码
if err != nil {//这里判断一下err,如果断开就跳出循环,关闭当前连接
fmt.Println(err.Error())
return
}
arr := strings.Split(string(b[:count]),":")//验证账号和密码
isbool,k:=config.Confirm(arr[0],arr[1],config.Clients)
if !isbool{
fmt.Println("用户名或者密码错误!")
return
}
for{//验证通过了,就一直保持连接接收信息
count, err := conn.Read(b)
if err != nil {//这里判断一下err,如果断开就跳出循环,关闭当前连接
fmt.Println(arr[0]+"客户端断开连接")
config.Clients.Infos[k]=Info{//断开连接就清空
Name: config.Clients.Infos[k].Name,
Cpuused: 0,
Memused: 0,
Memavailable: 0,
Swaptotal: 0,
Swapfree: 0,
Memtotal: 0,
Disktotal: 0,
Diskfree: 0,
Diskused: 0,
Netsend: 0,
Netrecv: 0,
Netup: "",
Netdown: "",
Uptime: 0,
}
break
}
err=json.Unmarshal(b[:count],&config.Clients.Infos[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 (config *Config) Confirm(u string,pd string,clients Clients) (bool,int){
for k,v := range config.File {
if v.Username == u && v.Password == pd{
fmt.Println(v.Username+"登录成功!")
clients.Infos[k].Name=v.Name
return true,k
}
}
return false,0
}
func (config *Config) Setname(clients []Info){
for k, v := range config.File {
clients[k].Name=v.Name
}
}