最近在学习Go语言网络编程,突然想到很久以前的用C语言写过的TCP广播聊天程序,然后就用Go尝试写了一遍,在此做个记录。
目录
1.广播结构
2.实现效果
3.源码
4.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\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] = 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\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


![[Python系列] Python虚拟环境Virtualenv](https://img-blog.csdnimg.cn/06af802d2b624df09aca795276cdf72c.png)
















