graph BT A(终端A) --> TCPServer B(终端B) --> TCPServer C(终端C) --> TCPServer TCPServer --> Postgresql Postgresql --> HTTPServer HTTPServer --> D(ClientA) HTTPServer --> E(ClientB) HTTPServer --> F(ClientC)
后端须要设计两个服务器,一个TCP,一个HTTP。TCP主要处理与终端的长链接交互,一个TCP链接对应一台终端设备,终端设备惟一标识使用IMEI。HTTP处理与前端的交互,前端须要获取全部可用的终端设备列表,向指定的终端发送命令。因此,为了方便从ip找到对应终端,而后从对应终端找到对应的conn,咱们就须要维护一个map:前端
type Terminal struct { authkey string imei string iccid string vin string tboxver string loginTime time.Time seqNum uint16 phoneNum string Conn net.Conn } var connManger map[string]*Terminal
至于为何要定义成指针的形式,是由于定义成指针后咱们能够直接修改map中元素结构体中对应的变量,而不须要从新定义一个元素再赋值。golang
var connManager map[string]*Terminal connManager = make(map[string]*Terminal) connManager["127.0.0.1:11000"]=&Terminal{} connManager["127.0.0.1:11001"]=&Terminal{} ... //此处可以轻松的修改对应的phoneNum修改 connManager["127.0.0.1:11001"].phoneNum = "13000000000"
相反,下面的这段代码修改起来就要繁琐很多:sql
var connManager map[string]Terminal connManager = make(map[string]Terminal) connManager["127.0.0.1:11000"]=Terminal{} connManager["127.0.0.1:11001"]=Terminal{} ... //此处会报错 connManager["127.0.0.1:11001"].phoneNum = "13000000000" //此处修改须要定义一个临时变量,相似于读改写的模式 term,ok:=connManager["127.0.0.1:11001"] term.phoneNum = "13000000000" connManager["127.0.0.1:11001"]=term
上面的代码一处会报错后端
cannot assign to struct field connManager["127.0.0.1:11001"].phoneNum in map
从上面的对比就能够看到,确实是定义成指针更加方便了。bash
TCP的长链接咱们选择这样的一种方式:服务器
若是熟悉socket的话,就知道socket一个服务器建立的基本步骤:socket
其中accept通常须要轮循调用。golang也基本是一样的流程。tcp
一个简单的TCP服务器示例:测试
package main import ( "fmt" "net" ) type Terminal struct { authkey string imei string iccid string vin string tboxver string phoneNum string Conn net.Conn } var connManager map[string]*Terminal func recvConnMsg(conn net.Conn) { addr := conn.RemoteAddr() var term *Terminal = &Terminal{ Conn: conn, } term.Conn = conn connManager[addr.String()] = term defer func() { delete(connManager, addr.String()) conn.Close() }() for { tempbuf := make([]byte, 1024) n, err := conn.Read(tempbuf) if err != nil { return } fmt.Println("rcv:", tempbuf[:n]) } } func TCPServer(addr string) { connManager = make(map[string]*Terminal) listenSock, err := net.Listen("tcp", addr) if err != nil { return } defer listenSock.Close() for { newConn, err := listenSock.Accept() if err != nil { continue } go recvConnMsg(newConn) } } func main() { TCPServer(":19903") }
如下是用来测试的客户端代码:ui
package main import ( "fmt" "net" "time" ) func main() { conn, err := net.Dial("tcp", ":19903") if err != nil { return } defer conn.Close() var n int = 0 n, err = conn.Write([]byte("123456")) if err != nil { return } fmt.Println("len:", n) for { time.Sleep(time.Second * 3) } }
测试结果:
$ ./server rcv: [49 50 51 52 53 54]