2.22 網路通訊4:TCP廣播
阿新 • • 發佈:2018-12-09
服務端實現
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("客戶端關閉")
}