這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
client.go------------------------------package mainimport ( "net" "fmt" "bufio" "echo/codec" "time")var quitSemaphore chan boolfunc main() { var tcpAddr *net.TCPAddr tcpAddr,_=net.ResolveTCPAddr("tcp","127.0.0.1:9999") conn,_:=net.DialTCP("tcp",nil,tcpAddr) //開啟串連 defer conn.Close() //關閉串連 fmt.Println("Connected!") go onMessageRecived(conn) //接收訊息 go sendMessage(conn) //發送訊息 <-quitSemaphore}// 發送訊息func sendMessage(conn *net.TCPConn) { //發送訊息 for{ time.Sleep(1 * time.Second) var msg string fmt.Scanln(&msg) if msg == "quit"{ quitSemaphore <- true break } //lk //b :=[]byte(msg +"\n") //處理加密 b ,_ := codec.Encode(msg+"\n") conn.Write(b) }}
server.go-----------------------------package mainimport ( "bufio" "fmt" "net" "echo/codec")// 用來記錄所有的用戶端串連var ConnMap map[string]*net.TCPConnfunc main() { var tcpAddr *net.TCPAddr ConnMap = make(map[string]*net.TCPConn) //初始化 tcpAddr,_=net.ResolveTCPAddr("tcp","127.0.0.1:9999") tcpListener,_:=net.ListenTCP("tcp",tcpAddr) //開啟tcp 服務 //退出時關閉 defer tcpListener.Close() for{ tcpConn,err :=tcpListener.AcceptTCP() if err !=nil { continue } fmt.Println("A client connected : "+ tcpConn.RemoteAddr().String()) // 新串連加入 map ConnMap[tcpConn.RemoteAddr().String()] = tcpConn go tcpPipe(tcpConn) }}//處理髮送過來的訊息func tcpPipe(conn *net.TCPConn) { ipStr :=conn.RemoteAddr().String() defer func() { fmt.Println("disconnected : "+ ipStr) conn.Close() }() //讀取資料 reader :=bufio.NewReader(conn) for { message ,err :=codec.Decode(reader)//reader.ReadString('\n') if err != nil { return } fmt.Println(string(message)) //這裡返回訊息改為廣播 boradcastMessage(conn.RemoteAddr().String()+":"+string(message)) }}//廣播給其它 func boradcastMessage(message string) { //遍曆所有用戶端並發訊息 for _,conn :=range ConnMap{ b,err :=codec.Encode(message) if err != nil { continue } conn.Write(b) }}
codec.go------------------------package codecimport ( "bytes" "encoding/binary" "bufio")func Encode(message string) ([]byte, error) { // 讀取訊息的長度 var length int32 = int32(len(message)) var pkg *bytes.Buffer = new(bytes.Buffer) // 寫入訊息頭 err := binary.Write(pkg, binary.LittleEndian, length) if err != nil { return nil, err } // 寫入訊息實體 err = binary.Write(pkg, binary.LittleEndian, []byte(message)) if err != nil { return nil, err } return pkg.Bytes(), nil}func Decode(reader *bufio.Reader) (string, error) { // 讀取訊息的長度 lengthByte, _ := reader.Peek(4) lengthBuff := bytes.NewBuffer(lengthByte) var length int32 err := binary.Read(lengthBuff, binary.LittleEndian, &length) if err != nil { return "", err } if int32(reader.Buffered()) < length+4 { return "", err } // 讀取訊息真正的內容 pack := make([]byte, int(4+length)) _, err = reader.Read(pack) if err != nil { return "", err } return string(pack[4:]), nil}
func onMessageRecived(conn *net.TCPConn) { reader :=bufio.NewReader(conn) for { //解密 msg,err := codec.Decode(reader)//reader.ReadString('\n') fmt.Println(msg) if err !=nil { quitSemaphore <- true break } }}