72-并发聊天室

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33781658/article/details/84574813


go并发聊天室

我们先来写简单的listen和conn


func main() {

	listener, err := net.Listen("tcp", "127.0.0.1:8080")
	if err != nil {
		fmt.Println("监听器创建失败...")
		return
	}
	defer listener.Close()
	fmt.Println("监听器创建成功...")

	go boardcaster()

	for {
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println("连接失败...")
			continue
		}
		defer conn.Close()

		go handler(conn)
	}

}

func handler(conn net.Conn) {
	addr := conn.RemoteAddr()
	fmt.Println(addr, "连接成功...")
}

func boardcaster() {
	fmt.Println("广播器正在运行...")
}


这是我们的聊天室的基本架构



然后我们完善一下broadcaster()方法
和handler()方法



func main() {

	//创建监听器
	listener, err := net.Listen("tcp", "127.0.0.1:8080")
	if err != nil {
		fmt.Println("创建监听器失败...")
		return
	}
	defer listener.Close()
	fmt.Println("创建监听器成功...")

	//启动广播
	go broadcaster()

	//循环创建连接
	for {
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println("连接失败...")
			continue
		}
		defer conn.Close()

		//处理conn连接
		handler(conn)
	}
}

func handler(conn net.Conn) {
	//获取addr
	addr := conn.RemoteAddr().String()
	fmt.Println(addr, "连接...")

	//创建client对象
	channel := make(chan string)
	cli := Client{addr, addr, channel}

	//输出msg
	go clientWriter(conn, cli.channel)

	//显示连接,发送消息,加入map
	cli.channel <- addr + " welcome"
	messages <- addr + " has arrived"
	entering <- cli

	//创建channel控制时间
	hasData := make(chan struct{})
	go func() {
		for {
			select {
			case <-hasData:
			case <-time.After(20 * time.Second):
				conn.Close()
			}
		}
	}()

	//循环输入
	scanner := bufio.NewScanner(conn)
	for scanner.Scan() {

		//发送时间channel消息
		hasData <- struct{}{}

		//扫描输入
		text := scanner.Text()
		if text == "#list" {
			list <- cli
		} else if len(text) > 8 && text[0:8] == "#rename|" {
			cli.name = text[8:]
			rename <- cli
		} else {
			messages <- cli.name + " : " + text
		}
	}

	//断开连接
	leaving <- cli
	messages <- cli.name + "has left"
}

//输出msg
func clientWriter(conn net.Conn, channel chan string) {
	for msg := range channel {
		fmt.Fprintln(conn, msg)
	}
}

//启动广播
func broadcaster() {
	//创建map
	clients := make(map[string]Client)

	//select监听
	for {
		select {
		case cli := <-entering:
			clients[cli.addr] = cli
		case cli := <-leaving:
			delete(clients, cli.addr)
		case msg := <-messages:
			for _, cli := range clients {
				cli.channel <- msg
			}
		case cli := <-list:
			for _, v := range clients {
				cli.channel <- v.name
			}
		case cli := <-rename:
			clients[cli.addr] = cli
		}
	}
}

//Client结构体
type Client struct {
	name    string
	addr    string
	channel chan string
}

//创建channel通道
var entering = make(chan Client)
var leaving = make(chan Client)
var messages = make(chan string)
var list = make(chan Client)
var rename = make(chan Client)




猜你喜欢

转载自blog.csdn.net/qq_33781658/article/details/84574813