社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
title: Go-远程控制项目(2)-server端
date: 2018-04-20 18:35:33
tags: [go, 语言]
categories: 科研
大神(github帐号: kingname), 项目源码地址:https://github.com/kingname/RemoteControl/ , 用python实现远程控制。本项目是想采用Go语言实现类似的远程控制。本节是粗写server端。
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))
}
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!")
}
}
由于python和go数据类型上的不同,python中发的都是字典形式的,如:
{"to": "", "from": "master", "command": "listSlave", "type": ""}
这在python中很容易键值对找到,但是到了go就必须得翻译,所以后期等整个完成了,需要把数据类型改换成更适合go语言,这样效率更高。
现在还没分析清楚python中如何确定slave和master的角色,后期写代码需要注意在初始化连接时,看如何确认。现在listSlave
返回的都是全部的,由master确定(它知道自己是哪个)。
每个连接都是一个goroutine,只需要记下slave的conn就好,master的不太需要,因为不可能由slave发给master,所以slave的conn(goroutine)不会跨conn向master的conn发送消息。而master发给slave的则可以用slavepool找到(并且消息的to字段决定了发给谁)。
这个人写的python会自动关闭socket,而每次发送时会新建连接,这样就不能永久使用MasterConn
.
masterConn.Write([]byte(message))
buf := make([]byte, 4096)
//应该是把conn中接收的数据写入到了buf中
nbyte, err := c.Read(buf)
//返回的是接收数据的长度
if err != nil {
panic(err)
}
//打印数据
fmt.Println("recv data:", string(buf[:nbyte]))
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"
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!