用Go语言写的一个多人聊天室

package main

import (
	"net"
	"fmt"
	"strings"
	"time"
)

//保存在线用户
var onlineMap map[string]Client = make(map[string]Client)

var message  = make(chan string)

type Client struct {
	C chan string
	Name string
	Addr string
}


func main()  {
	lis,e1 := net.Listen("tcp","127.0.0.1:8888")
	if e1 != nil {
		fmt.Println("e1 = ",e1)
		return
	}
	defer lis.Close()

	//将某个用户上线的通知发送个所有的在线用户,这里会阻塞,直到下面往message发送消息
	go Manager()

	for {
		conn,e2 := lis.Accept()
		if e2 != nil {
			fmt.Println("e2 = ",e2)
			continue
		}

		//每一个请求过来都创建一个新的协程
		go HandleConn(conn)
	}
}
func Manager() {
	for {
		msg := <- message
		//遍历map,给map的每一个元素发送消息
		for _,cli := range onlineMap {
			//将msg信息发送给map每一个元素
			cli.C <- msg
		}
	}
}
func HandleConn(conn net.Conn)  {
	defer conn.Close()
	cliAddr := conn.RemoteAddr().String()

	cli := Client{make(chan string),cliAddr,cliAddr}
	//放到map中
	onlineMap[cliAddr] = cli
	//新开一个协程,专门用来发送信息给当前的客户端,这里主要一有消息就开始消费
	go WriteMsgToClient(cli,conn)

	//这里就往message发送信息了,Manager()方法开始向客户端发送消息了
	message <- "[" + cli.Addr + "]" + cli.Name + ":login"

	//提示我是谁
	cli.C <- "[" + cli.Addr + "]" + cli.Name + ":" + "i am here"

	isQuit := make(chan bool)
	hasData := make(chan bool)


	//读取客户端发来的数据
	go func() {
		b1 := make([]byte,1024)
		for {
			n1,e1 := conn.Read(b1)
			if n1 == 0 {
				isQuit <- true
				fmt.Println("conn.Read err = ", e1)
				return
			}

			m1 := string(b1[:n1 - 1])
			if "who" == m1 {
				conn.Write([]byte("user list : \n"))
				for _,tmp := range onlineMap {
					msg := tmp.Addr + ":" + tmp.Name + "\n"
					conn.Write([]byte(msg))
				}
			}else if len(m1) >= 8 && m1[:6] == "rename" {
				name := strings.Split(m1,"|")[1]
				cli.Name = name
				onlineMap[cliAddr] = cli
				conn.Write([]byte("rename success!\n"))
			}else {
				message <- "[" + cli.Addr + "]" + cli.Name + ":" + string(b1[:n1 - 1])
			}
			hasData <- true
		}
	}()

	for {
		select {
		case <- isQuit:
			delete(onlineMap,cliAddr)
			message <- "[" + cli.Addr + "]" + cli.Name + ":" + "login out!"
			return
		case <- hasData:

		case <- time.After(30 * time.Second):
			delete(onlineMap,cliAddr)
			message <- 	"[" + cli.Addr + "]" + cli.Name + ":" + "time out leave out!"
			return 
		}
	}

}
func WriteMsgToClient(cli Client, conn net.Conn) {
	for mse := range cli.C {
		conn.Write([]byte(mse + "\n"))
	}
}


猜你喜欢

转载自blog.csdn.net/weixin_38104426/article/details/81003681