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]