網路通訊4:TCP廣播
阿新 • • 發佈:2018-12-21
服務端實現
import ( "fmt" "net" "os" "strings" ) //儲存客戶端連線, key,ip埠,value 連結物件 var onlineConnsMap = make(map[string]net.Conn) //訊息佇列,緩衝區 var messageQueue = make(chan string, 1000) //訊息,處理程式退出 var quitchan = make(chan bool) func CheckErrorS(err error) { if err != nil { fmt.Println("網路錯誤", err.Error()) os.Exit(1) } } func Processinfo(conn net.Conn) { buf := make([]byte, 1024) //開創緩衝區 defer func() { //關閉連線 conn.Close() fmt.Println("連線已關閉:",conn.RemoteAddr()) }() for { n, err := conn.Read(buf) //讀取資料 if err != nil { fmt.Println("讀取客戶端訊息出錯,err=",err) break } if n != 0 { //訊息處理, message := string(buf[0:n]) fmt.Printf("受到客戶端%v訊息:%s\n",conn.RemoteAddr(),message) //訊息佇列儲存訊息 messageQueue <- message fmt.Println("該條訊息已加入佇列...") }else{ fmt.Println("讀取客戶端訊息長度為0") } } } //訊息的協程 func consumeMessage() { for { select { case message := <-messageQueue: //取出訊息 fmt.Println("已從佇列中取出訊息") strs := strings.Split(message, "#") //字串切割 if len(strs) > 1 { //127.0.0.1:12345#去死 //擷取地址並裁減頭尾空白 addr := strs[0] addr = strings.TrimSpace(addr) //擷取內容 msg := strs[1] //給所有客戶端群發此訊息 /*for addr, conn := range onlineConnsMap { //迴圈線上列表 _, err := conn.Write([]byte(msg)) fmt.Println("伺服器傳送訊息", msg, "給", addr) if err != nil { fmt.Println("線上連結傳送失敗") } }*/ //@某人,發訊息 if conn, ok := onlineConnsMap[addr]; ok { _, err := conn.Write([]byte(msg)) fmt.Println("伺服器傳送訊息", msg) if err != nil { fmt.Println("線上連結傳送失敗") } } } case <-quitchan: //處理退出 os.Exit(0) } } } func main() { //建立TCP伺服器 listener, err := net.Listen("tcp", "127.0.0.1:8898") CheckErrorS(err) defer listener.Close() //關閉網路 fmt.Println("伺服器正在等待") go consumeMessage() for { conn, err := listener.Accept() //新的客戶端連線 CheckErrorS(err) //處理每一個客戶端 addr := fmt.Sprint(conn.RemoteAddr()) //取出地址 onlineConnsMap[addr] = conn fmt.Println("客戶端列表") fmt.Println("-------------------") for key := range onlineConnsMap { //迴圈每一個連結 fmt.Println(key) } go Processinfo(conn) } }
客戶端呢實現
import ( "fmt" "net" "bufio" "os" ) func CheckErrorC(err error) { if err != nil { fmt.Println("網路錯誤", err.Error()) } } func MessageSend(conn net.Conn) { var input string for { reader := bufio.NewReader(os.Stdin) //讀取鍵盤輸入 data, _, _ := reader.ReadLine() //讀取一行 input = string(data) //鍵盤輸入轉化為字串 if input == "exit" { conn.Close() fmt.Println("客戶端關閉") break } _, err := conn.Write([]byte(input)) //輸入寫入字串 fmt.Println("傳送訊息", input) if err != nil { conn.Close() fmt.Println("客戶端關閉") break } } } func main() { conn, err := net.Dial("tcp", "127.0.0.1:8898") //建立TCP伺服器 defer conn.Close() //延遲關閉網路連線 CheckErrorC(err) //檢查錯誤 go MessageSend(conn) //開啟一個協程,處理髮送 //conn.Write([]byte("hello nimei")) //協程,負責收取訊息 buf := make([]byte, 1024) for { numOfBytes, err := conn.Read(buf) CheckErrorC(err) fmt.Println("收到伺服器訊息", string(buf[:numOfBytes])) } fmt.Println("客戶端關閉") }