最近在学习Go语言网络编程,突然想到很久以前的用C语言写过的TCP广播聊天程序,然后就用Go尝试写了一遍,在此做个记录。
目录
1.广播结构
2.实现效果
3.源码
4.Go语言学习参考网站
1.广播结构
2.实现效果
服务器:
客户端1:
客户端2:
客户端3:
3.源码
server.go
package mainimport ("encoding/json""fmt""net""strings"
)// client info
type Client struct {Chan chan []byteAddr string
}// 广播信息
type Msg struct {Content stringUser 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\n", 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] = clientcontent := 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 mainimport ("bufio""encoding/json""fmt""net""os"
)// 广播信息
type Msg struct {Content stringUser 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 Msgjson.Unmarshal(result, &msg)fmt.Printf("%s: %s\n", msg.User, msg.Content)}
}func writeMsg(conn net.Conn) {for true {// 从标准输入生成读对象reader := bufio.NewReader(os.Stdin)// 读到换行content, _ := reader.ReadBytes('\n')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