[TOC] ## 概述 ``` go build server.go ``` 1.监听端口 : 9090 2.发送实例 ``` 加入会议 nick|123 聊天 say|123|hello,word|121 广播 sayall|123|hello,word 退出 quit|123 ``` ## 文件 server.go ``` package main import ( "fmt" "net" "strings" "github.com/lunny/log" ) type ConList struct { Con map[string]net.Conn Count int } func (c *ConList) Add(nickName string, Con net.Conn) { if nickName == "" { log.Error("昵称为空") return } if Con == nil { log.Error("Con 为空") return } exit := c.IsExit(nickName) if exit { log.Error("存在 nickname :" + nickName) return } fmt.Println(Con.RemoteAddr(), "-->", nickName) //nick占在数组下标0上,客户端上写的昵称占在数组下标1上 c.Con[nickName] = Con c.Count++ //发送通知给所有人入 c.sendAll(nickName + " --> join") fmt.Println("当前连接数 count", c.Count) } //判断昵称是否存在 func (c *ConList) IsExit(nickName string) bool { for k, _ := range c.Con { if k == nickName { return true } } return false } func (c *ConList) Remove(nickName string) { if nickName == "" { log.Error("nickName 为空") return } exit := c.IsExit(nickName) if !exit { log.Error("不存在 nickname :" + nickName) return } err := c.Con[nickName].Close() if err != nil { log.Error("删除失败") return } delete(c.Con, nickName) fmt.Println("删除成功") c.Count-- fmt.Println("当前连接数 count", c.Count) } func (c *ConList) Send(nickName string, sendName string, msg string) { if nickName == "" { log.Error("nickname 为空") return } if sendName == "" { log.Error("sendName 为空") return } if msg == "" { log.Error("msg 参数为空") } exit1 := c.IsExit(nickName) if !exit1 { log.Error("nickname 不存在" + nickName) return } exit2 := c.IsExit(nickName) if !exit2 { log.Error("sendName 不存在" + sendName) return } _, err := c.Con[sendName].Write([]byte(msg)) if err != nil { log.Error("发送失败", err) } fmt.Println("发送成功") } func (c *ConList) sendAll(s string) { for _, v := range c.Con { v.Write([]byte(s)) } } var ( ConnMap = ConList{Con: make(map[string]net.Conn), Count: 0} //声明一个集合 ) func main() { listen_socket, err := net.Listen("tcp", ":9090") //打开监听接口 if err != nil { fmt.Println("server start error") } defer listen_socket.Close() fmt.Println("server is wating port:9090 ....") for { conn, err := listen_socket.Accept() //收到来自客户端发来的消息 if err != nil { fmt.Println("conn fail ...") } fmt.Println(conn.RemoteAddr(), "connect successed") go handle(conn) //创建线程 } } func handle(conn net.Conn) { for { data := make([]byte, 255) //创建字节流 (此处同 一对一 通信) num, err := conn.Read(data) //声明并将从客户端读取的消息赋给msg_read 和err if num == 0 || err != nil { continue } //解析协议 msg_str := strings.Split(string(data[0:num]), "|") //将从客户端收到的字节流分段保存到msg_str这个数组中 switch msg_str[0] { case "nick": //加入聊天室 nick|121 ConnMap.Add(msg_str[1], conn) case "say": //转发消息 say|121|hello,word|121 ConnMap.Send(msg_str[1], msg_str[3], msg_str[2]) case "quit": //退出 quit|123 ConnMap.Remove(msg_str[1]) } } } ``` client.go ``` package main import ( "fmt" "log" "net" "os" ) func main() { Start(os.Args[1]) } func Start(tcpAddrStr string) { tcpAddr, err := net.ResolveTCPAddr("tcp4", tcpAddrStr) if err != nil { log.Printf("Resolve tcp addr failed: %v\n", err) return } // 向服务器拨号 conn, err := net.DialTCP("tcp", nil, tcpAddr) if err != nil { log.Printf("Dial to server failed: %v\n", err) return } // 向服务器发消息 go SendMsg(conn) // 接收来自服务器端的广播消息 buf := make([]byte, 1024) for { length, err := conn.Read(buf) if err != nil { log.Printf("recv server msg failed: %v\n", err) conn.Close() os.Exit(0) break } fmt.Println(string(buf[0:length])) } } // 向服务器端发消息 func SendMsg(conn net.Conn) { username := conn.LocalAddr().String() for { var input string // 接收输入消息,放到input变量中 fmt.Scanln(&input) if input == "/q" || input == "/quit" { fmt.Println("Byebye ...") conn.Close() os.Exit(0) } // 只处理有内容的消息 if len(input) > 0 { msg := username + " say:" + input _, err := conn.Write([]byte(msg)) if err != nil { conn.Close() break } } } } ```