go學習(8)TCP程式設計
阿新 • • 發佈:2018-12-17
go網路程式設計簡單易上手,tcp可以很容易實現一個客戶端一個執行緒(goroutine),業務處理清楚明瞭。
服務端:
package main import ( "fmt" "net" ) const ( MAX_MSG_LENGTH = 1024 //每次最大收多少資料 ) //處理玩家資料 func Echo(c net.Conn) { fmt.Printf("Client conn %s", c.RemoteAddr().String()) data := make([]byte, MAX_MSG_LENGTH) //用於接收資料緩衝 defer c.Close() //defer 關閉連線 for { //迴圈處理客戶端資料 data = []byte{} n, err := c.Read(data) //這裡阻塞等到客戶端資料到來 if err != nil { fmt.Printf("Read message failed:%s\n", err.Error()) return } if n > 0 { c.Write(data) //將客戶端的資料傳送回去 } } } func main() { fmt.Printf("Server is ready...\n") l, err := net.Listen("tcp", ":7777") //繫結協議,埠 if err != nil { fmt.Printf("Failure to listen:%s\n", err.Error()) return } for { if c, err := l.Accept(); err == nil { //接受連線 go Echo(c) //每一個Client啟動一個協程,處理資料 } } }
客戶端:
package main import ( "bufio" "fmt" "net" "os" "time" ) //客戶端類 type Client struct { conn1 net.Conn //連線 isAlive bool //是否活躍 sendStr chan string recvStr chan string } //客戶端的連線函式 func (c *Client) Connect() bool { if c.isAlive { //已經連線成功 return true } else { var err error c.conn1, err = net.Dial("tcp", "127.0.0.1:7777") //連線服務端 if err != nil { fmt.Printf("Failure to connect:%s\n", err.Error()) return false } c.isAlive = true } return true } //傳送資料介面 func (c *Client) Echo() { line := <-c.sendStr //line為要傳送的資料(從傳送管道取資料) c.conn1.Write([]byte(line)) //轉為byte[]傳送 buf := make([]byte, 1024) n, err := c.conn1.Read(buf) //等待服務端返回資料 if err != nil { c.recvStr <- string("Server close...") c.conn1.Close() c.isAlive = false return } time.Sleep(1 * time.Second) c.recvStr <- string(buf[0:n]) //收到的資料寫入管道recvStr } func Work(tc *Client) { if !tc.isAlive { if tc.Connect() { tc.Echo() } else { <-tc.sendStr tc.recvStr <- string("Server close...") } } else { tc.Echo() } } func main() { var tc Client //客戶端例項 tc.sendStr = make(chan string) //建立傳送、接收管道 tc.recvStr = make(chan string) if !tc.Connect() { return } r := bufio.NewReader(os.Stdin) //從命令列接收資料 for { switch line, ok := r.ReadString('\n'); true { //讀到換行線束 case ok != nil: fmt.Printf("bye bye!\n") return default: go Work(&tc) tc.sendStr <- line s := <-tc.recvStr //等待接收到資料,這裡會阻塞到有資料為止 fmt.Printf("recv:%s\n", s) } } }