Ubuntu下Go语言TCP广播服务器实现
最近在学习Go语言网络编程,突然想到很久以前的用C语言写过的TCP广播聊天程序,然后就用Go尝试写了一遍,在此做个记录。
1.广播结构
2.实现效果
服务器:
客户端1:
客户端2:
客户端3:
3.源码
server.go
package main import ( "encoding/json" "fmt" "net" "strings" ) // client info type Client struct { Chan chan []byte Addr string } // 广播信息 type Msg struct { Content string User string } // 客户端信息存储,IP和端口字符串为key var onlineClients = make(map[string]Client) // 广播消息的通道 var broadcastCh = make(chan Msg) // 遍历通知客户端 func broadcastMessageManager() { for { //广播通道取数据 msg := <-broadcastCh //遍历客户端发送数据 for _, client := range onlineClients { msgBytes, _ := json.Marshal(msg) client.Chan <- msgBytes } } } // 接收客户端消息,并将消息放入广播消息通道 func readClient(conn net.Conn) { for true { data := make([]byte, 1024) n, _ := conn.Read(data) content := strings.TrimSpace(string(data[:n])) if len(content) <= 0 { continue } broadcastCh <- Msg{Content: content, User: conn.RemoteAddr().String()} fmt.Printf("%s say: %s ", conn.RemoteAddr().String(), content) } } // 通知客户端消息 func notifyMsgToClient(conn net.Conn, client Client) { for { msgBytes := <-client.Chan _, _ = conn.Write(msgBytes) } } func handleConnect(conn net.Conn) { addr := conn.RemoteAddr().String() fmt.Println("connect cilent: ", conn.RemoteAddr().String()) client := Client{make(chan []byte), addr} onlineClients[addr] = client content := client.Addr + " coming!" broadcastCh <- Msg{Content: content, User: "system info"} go readClient(conn) go notifyMsgToClient(conn, client) } func main() { fmt.Println("server starting ...") listener, err := net.Listen("tcp", "127.0.0.1:8181") if err != nil { fmt.Println("net.Listen err: ", err) return } //遍历通知客户端 go broadcastMessageManager() for { conn, err := listener.Accept() if err != nil { fmt.Println("listener.Accept err: ", err) continue } //goroutine处理用户连接 go handleConnect(conn) } }
client.go
package main import ( "bufio" "encoding/json" "fmt" "net" "os" ) // 广播信息 type Msg struct { Content string User string } func readMsg(conn net.Conn) { for { res := make([]byte, 1024) n, err := conn.Read(res) if err != nil { fmt.Println(err) return } result := res[:n] var msg Msg json.Unmarshal(result, &msg) fmt.Printf("%s: %s ", msg.User, msg.Content) } } func writeMsg(conn net.Conn) { for true { // 从标准输入生成读对象 reader := bufio.NewReader(os.Stdin) // 读到换行 content, _ := reader.ReadBytes( ) if len(content) <= 0 { continue } // 发送数据 conn.Write(content) } } func main() { conn, err := net.Dial("tcp", "127.0.0.1:8181") if err != nil { fmt.Println(err) return } defer conn.Close() // 起goroutine接收服务器广播的消息 go readMsg(conn) // 命令行接收输入并发送给服务器 writeMsg(conn) }
4.Go语言学习参考网站
Go言入门教程: http://c.biancheng.net/golang/
Go编程参考: http://www.yuan316.com/post/Go%E8%AF%AD%E8%A8%80/
Go语言标准库: https://pkg.go.dev/std
Go虎贲 https://www.zhihu.com/column/c_1438631789279076353
下一篇:
用遗传算法解决柔性车间调度问题