package main
import (
"bufio"
"fmt"
"log"
"net"
)
/*
简单聊天室需求分析:
因为是即时通信,所有使用同步通道
需要广播群聊消息到各个客户端:
1. 所有需要将所有客户端进行统一管理
1) 删除一个离开的用户
2) 加入一个刚来的用户
2. 对一个客户端消息进行群发(包括发给自己)
1)直接遍历发送就行了
对接客户端协程要做的事情:
1. 写入信息
2. 断开连接时,关闭连接
*/
func main() {
//创建服务端
listener, err := net.Listen("tcp", "localhost:8080")
if err != nil {
log.Fatal(err)
}
//开启信息广播,连接管理
go broadcaster()
for {
conn, err := listener.Accept()
if err != nil {
log.Println(err)
continue
}
go handleConn(conn)
}
}
func handleConn(conn net.Conn) {
//对进来的人员进行欢迎
who := conn.RemoteAddr().String()
messages <- "欢迎:" + who + " 加入群聊!"
client := make(chan string)
enter <- client
//对客户端进行信息进行会写
go func() {
for msg := range client {
fmt.Println(msg)
fmt.Fprintf(conn, "%s\n", msg)
}
}()
//接收客户端发来的信息,并进行广播
input := bufio.NewScanner(conn)
for input.Scan() {
messages <- who + ": " + input.Text()
}
leave <- client
conn.Close()
//对人员的离开进行通知
messages <- who + " 退出了群聊!"
}
type client chan<- string
var (
messages = make(chan string)
enter = make(chan client)
leave = make(chan client)
)
func broadcaster() {
clients := make(map[client]bool)
for {
select {
case msg := <-messages:
for client, _ := range clients {
client <- msg
}
case client := <-enter:
clients[client] = true
case client := <-leave:
delete(clients, client)
close(client)
}
}
}
我们在cmd窗口进行测试:我使用的是 telnet 127.0.0.1 8080 这个telnet要是使用不了,可以百度一下!