Go-远程控制项目(2)-server端 - Go语言中文社区

Go-远程控制项目(2)-server端


title: Go-远程控制项目(2)-server端
date: 2018-04-20 18:35:33
tags: [go, 语言]
categories: 科研


大神(github帐号: kingname), 项目源码地址:https://github.com/kingname/RemoteControl/ , 用python实现远程控制。本项目是想采用Go语言实现类似的远程控制。本节是粗写server端。

项目

TEST1-完成listslave功能

package main

import (

    "net"
    "fmt"

    "regexp"

    "log"

    "sync"

    "strings"
)

const (
    bufsize  = 4096*100
    MASTER = "master"
    SLAVE = "slave"
    SERVER = "server"
    )



var (
    slaveConnPool []net.Conn
    masterConn net.Conn
     mu sync.Mutex
    )



func main() {
    listen, err := net.Listen("tcp","127.0.0.1:5000")
    if err != nil {
        panic(err)
    }
    for {
        conn, err := listen.Accept()
        if err != nil {
            panic(err)
        }
        fmt.Println("========================na new conn: ", conn.RemoteAddr().String())
        AddslaveConnPool(conn)

        go handleConn(conn)
    }
    defer listen.Close()

}

func handleConn(c net.Conn)  {
    defer c.Close()
    for {

        buf := make([]byte, bufsize)
        nbyte, err := c.Read(buf)
        if err != nil {
            log.Printf("the socker has been closed by the %s", c.RemoteAddr().String())
            break
        }
        fmt.Println("recv data:", string(buf[:nbyte]))



        to, from, cmdString, cmdType := analyseCommand(string(buf[:nbyte]))
        fmt.Printf("from: %s, to: %s, cmd: %s, type: %sn", from, to ,cmdString, cmdType)

        //add to slavepool
        if from == MASTER {
            masterConn = c
            //delete the master conn from pool
            DelslaveConnPool(c)

            dispatch(to, from, cmdString, cmdType)

        } else {
            log.Println("don't know who send this message")
        }


    }

}

func AddslaveConnPool(c net.Conn)  {
    mu.Lock()
    defer mu.Unlock()
    slaveConnPool = append(slaveConnPool, c)
    fmt.Println("conn pool :", slaveConnPool)
}

func DelslaveConnPool(c net.Conn)  {
    mu.Lock()
    defer mu.Unlock()
    //fmt.Println("pool before delete", slaveConnPool)
    var pool []net.Conn
    for _, v := range slaveConnPool {
        if v == c {

        } else {
            pool = append(pool, v)
        }
    }
    slaveConnPool = pool
    //fmt.Println("pool after delete", slaveConnPool)
}

//return to, from, cmdString and cmdType
func analyseCommand(data string) ( _,_,_,_ string) {
    //re := regexp.MustCompile(`"to"[^"]+"([^"]+)"[^"]+"from"[^"]+"([^"]+)"[^"]+"command"[^"]+"([^"+])"[^"]+"type"[^"]+"([^"]+)".+`)

    re := regexp.MustCompile(`"to"[^"]+"([^"]*)"[^"]+"from"[^"]+"([^"]*)"[^"]+"command"[^"]+"([^"]*)"[^"]+"type"[^"]+"([^"]*)"`)
    match := re.FindStringSubmatch(data)

    if len(match) < 5 {
        log.Println("not enough arguments! please input again...")
        return
    } else {
        return match[1], match[2], match[3], match[4]
    }
}

func dispatch(to, from, cmdString, cmdType string)  {
    if to == SERVER {
        cmdtoServer(cmdString, cmdType)
    } else if to == SLAVE {
        cmdtoSlave(cmdString, cmdType)
    } else if to == "" {
        cmdtoServer(cmdString, cmdType)
    } else {
        fmt.Println("wrong sender or wrong reciever")
    }
}

func cmdtoServer(cmdString, cmdType string)  {

    if cmdString == "listSlave" {
        slavelist := listSlave()
        fmt.Println("slavelist:", slavelist)
        SendtoMaster(slavelist)
    }
}

func cmdtoSlave(cmdString, cmdType string)  {

}

func listSlave() []string {
    mu.Lock()
    defer mu.Unlock()
    var list  []string
    for _, c := range slaveConnPool{
        list = append(list, c.RemoteAddr().String())
    }
    return list
}

func SendtoMaster(list []string)  {
    //{"slaveList": ["127.0.0.1-7345", "127.0.0.1"]}#finished#
    message := `{"slaveList": ["`
    for k, v := range list {
        v = strings.Replace(v, ":", "-", -1)
        message += v+`"`
        if k < len(list) - 1 {
            message += `, "`
        }
    }
    message += `]}#finished#`

    fmt.Println("message to master:", message)
    masterConn.Write([]byte(message))
}

TEST2-完成发送命令

package main

import (

    "net"
    "fmt"

    "regexp"

    "log"

    "sync"

    "strings"
)

const (
    bufsize  = 4096*100
    MASTER = "master"
    SLAVE = "slave"
    SERVER = "server"
    )



var (
    slaveConnPool []net.Conn
    masterConn net.Conn
     mu sync.Mutex
    )



func main() {
    listen, err := net.Listen("tcp","127.0.0.1:5000")
    if err != nil {
        panic(err)
    }
    for {
        conn, err := listen.Accept()
        if err != nil {
            panic(err)
        }
        fmt.Println("========================na new conn: ", conn.RemoteAddr().String())
        AddslaveConnPool(conn)

        go handleConn(conn)
    }
    defer listen.Close()

}

func handleConn(c net.Conn)  {
    defer c.Close()
    for {

        buf := make([]byte, bufsize)
        nbyte, err := c.Read(buf)
        if err != nil {
            log.Printf("the socker has been closed by the %s", c.RemoteAddr().String())
            break
        }
        fmt.Println("recv data:", string(buf[:nbyte]))

        to, from, cmdString, cmdType := analyseCommand(string(buf[:nbyte]))
        fmt.Printf("from: %s, to: %s, cmd: %s, type: %sn", from, to ,cmdString, cmdType)

        //add to slavepool
        if from == MASTER {
            masterConn = c
            //delete the master conn from pool
            DelslaveConnPool(c)

            dispatch(to, from, cmdString, cmdType)

        } else {
            log.Println("don't know who send this message")
        }
    }
}

func AddslaveConnPool(c net.Conn)  {
    mu.Lock()
    defer mu.Unlock()
    slaveConnPool = append(slaveConnPool, c)
    fmt.Println("conn pool :", slaveConnPool)
}

func DelslaveConnPool(c net.Conn)  {
    mu.Lock()
    defer mu.Unlock()
    //fmt.Println("pool before delete", slaveConnPool)
    var pool []net.Conn
    for _, v := range slaveConnPool {
        if v == c {
        } else {
            pool = append(pool, v)
        }
    }
    slaveConnPool = pool
    //fmt.Println("pool after delete", slaveConnPool)
}

//return to, from, cmdString and cmdType
func analyseCommand(data string) ( _,_,_,_ string) {
    //re := regexp.MustCompile(`"to"[^"]+"([^"]+)"[^"]+"from"[^"]+"([^"]+)"[^"]+"command"[^"]+"([^"+])"[^"]+"type"[^"]+"([^"]+)".+`)

    re := regexp.MustCompile(`"to"[^"]+"([^"]*)"[^"]+"from"[^"]+"([^"]*)"[^"]+"command"[^"]+"([^"]*)"[^"]+"type"[^"]+"([^"]*)"`)
    match := re.FindStringSubmatch(data)

    if len(match) < 5 {
        log.Println("not enough arguments! please input again...")
        return
    } else {
        return match[1], match[2], match[3], match[4]
    }
}

func dispatch(to, from, cmdString, cmdType string)  {
    if to == SERVER || to == ""{
        cmdtoServer(cmdString, cmdType)
    } else {
        cmdtoSlave(to, from, cmdString, cmdType)
    }
}

func cmdtoServer(cmdString, cmdType string)  {

    if cmdString == "listSlave" {
        slavelist := listSlave()
        fmt.Println("slavelist:", slavelist)
        SendtoMaster(slavelist)
    }
}

func cmdtoSlave(to, from, cmdString, cmdType string)  {
    mu.Lock()
    defer mu.Unlock()

    for _, c := range slaveConnPool{
        if c.RemoteAddr().String() == strings.Replace(to, "-", ":", -1) {
            SendtoSlave(c , cmdString, cmdType)
        }
    }
}

func listSlave() []string {
    mu.Lock()
    defer mu.Unlock()
    var list  []string
    for _, c := range slaveConnPool{
        list = append(list, c.RemoteAddr().String())
    }
    return list
}

func SendtoMaster(list []string)  {
    //{"slaveList": ["127.0.0.1-7345", "127.0.0.1"]}#finished#
    message := `{"slaveList": ["`
    for k, v := range list {
        v = strings.Replace(v, ":", "-", -1)
        message += v+`"`
        if k < len(list) - 1 {
            message += `, "`
        }
    }
    message += `]}#finished#`

    fmt.Println("message to master:", message)
    masterConn.Write([]byte(message))
}

func SendtoSlave(c net.Conn, cmdString, cmdType string)  {
    if cmdType == "commandInConfig" {
        message :=  `{"type": "commandInConfig", "command": "` + cmdString + `"}#finished#`
        fmt.Println("message to Slave:", message)
        c.Write([]byte(message))
    } else {
        log.Println("don't know the cmd type!")
    }
}

附录

后期事项

事项1-数据类型

由于python和go数据类型上的不同,python中发的都是字典形式的,如:

{"to": "", "from": "master", "command": "listSlave", "type": ""}

这在python中很容易键值对找到,但是到了go就必须得翻译,所以后期等整个完成了,需要把数据类型改换成更适合go语言,这样效率更高。

事项2-初始化角色确认

现在还没分析清楚python中如何确定slave和master的角色,后期写代码需要注意在初始化连接时,看如何确认。现在listSlave返回的都是全部的,由master确定(它知道自己是哪个)。

事项3-goroutine

每个连接都是一个goroutine,只需要记下slave的conn就好,master的不太需要,因为不可能由slave发给master,所以slave的conn(goroutine)不会跨conn向master的conn发送消息。而master发给slave的则可以用slavepool找到(并且消息的to字段决定了发给谁)。

事项4-socket关闭

这个人写的python会自动关闭socket,而每次发送时会新建连接,这样就不能永久使用MasterConn.

事项5-发送数据

masterConn.Write([]byte(message))

相关知识

Read接口的使用

buf := make([]byte, 4096)
//应该是把conn中接收的数据写入到了buf中
nbyte, err := c.Read(buf)
//返回的是接收数据的长度

if err != nil {
   panic(err)
}
//打印数据
fmt.Println("recv data:", string(buf[:nbyte]))

if else格式

if num := 9; num < 0 {
      fmt.Println(num, "is negative")
  } else if num < 10 {
      fmt.Println(num, "has 1 digit")
  } else {
      fmt.Println(num, "has multiple digits"
  }
版权声明:本文来源简书,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://www.jianshu.com/p/ad1b54b7c90d
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-01-12 12:57:21
  • 阅读 ( 1078 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢