功能需求:
创建一个聊天室,实现群聊和单聊的功能,直接输入为群聊,@某人后输入为单聊
效果图:
群聊:
单聊:
服务端:
package main import ( "fmt" "net" "strings" ) type info struct { conn net.Conn name string } var ch_all chan string = make(chan string) var ch_one chan string = make(chan string) var ch_who chan string = make(chan string) var infos map[string]info = make(map[string]info) func handle(conn net.Conn) { defer conn.Close() buf := make([]byte, 100) n, _ := conn.Read(buf) name := string(buf[:n]) var oneinfo info oneinfo.conn = conn oneinfo.name = name addr := conn.RemoteAddr().String() infos[addr] = oneinfo msg := name + "进入聊天室" ch_all <- msg for { n, _ := conn.Read(buf) if n == 0 { fmt.Printf("%s断开连接 ", addr) msg = name + "离开聊天室" delete(infos, addr) ch_all <- msg fmt.Println(msg) return } if string(buf[:n])[0] == '@' { sli := strings.Fields(string(buf[1:n])) //隔开 who := sli[0] msg = strings.Join(sli[1:], "") //后边的再拼接回去 ch_who <- who ch_one <- name + "->me : " + msg //单发 continue } ch_all <- name + "->all : " + string(buf[:n]) //群发 } } func sendone() { for { who := <-ch_who msg := <-ch_one for _, v := range infos { if v.name == who { v.conn.Write([]byte(msg)) break } } } } func sendall() { for { msg := <-ch_all for _, val := range infos { val.conn.Write([]byte(msg)) } } } func main() { listener, _ := net.Listen("tcp", ":9009") defer listener.Close() go sendall() go sendone() for { conn, _ := listener.Accept() fmt.Printf("%s建立连接 ", conn.RemoteAddr().String()) go handle(conn) } }
客户端:
package main import ( "bufio" "fmt" "net" "os" ) func scandata(conn net.Conn) { for { //设置可以读取带空格的myscan myscan := bufio.NewReader(os.Stdin) buf, _, _ := myscan.ReadLine() if string(buf) == "q" { os.Exit(0) } conn.Write(buf) } } func main() { conn, _ := net.Dial("tcp", "127.0.0.1:9009") buf := make([]byte, 1024) args := os.Args conn.Write([]byte(args[1])) go scandata(conn) for { n, _ := conn.Read(buf) fmt.Println(string(buf[:n])) } }