go语言编写一个聊天室--服务端

该博客介绍了如何使用Go语言编写一个简易的聊天室。首先定义了用户结构体,包含ID、IP、进入时间及消息通道。接着初始化了用户进入、离开和消息发送的通道。然后实现了广播用户消息、发送消息和处理用户连接的方法。主函数中创建TCP连接,并通过goroutines处理用户连接和消息。这个简易聊天室能够实现用户之间的消息广播和交互。
摘要由CSDN通过智能技术生成

使用go语言编写一个简易版的聊天室,新建server.go,这个是服务端的代码,后续贴上客户端的代码

  • 建立一个用户结构体用于存储进来的用户信息,里面包含用户id,ip地址,进入的时间,还有一个channel用来发送消息的
type User struct {
	ID             int
	Addr           string
	EnterAt        time.Time
	MessageChannel chan string
}

  • 然后初始化三个channel,分别是用户进入的时候,用户离开的时候,用户发送消息的时候的用来通信的
var (
	enteringChannel = make(chan *User)

	leavingChannel = make(chan *User)

	messageChannel = make(chan string, 5)
)
  • 然后建一个发送消息的方法
// 新开一个goroutine给用户发送消息
func sendMessage(conn net.Conn, ch <-chan string) {
	for msg := range ch {
		fmt.Fprintln(conn, msg)
	}

}
  • 新增一个用于广播用户消息给所有人的方法, 新用户进来,用户消息,用户离开
func broadcaster() {
	// 使用结构体map来存储所有用户信息
	users := make(map[*User]struct{})
	for {
		select {
		case user := <-enteringChannel:
			// 新用户进入保存到map里面
			users[user] = struct{}{}
		case user := <-leavingChannel:
			// 用户退出后,删除掉这个用户
			delete(users, user)
		case msg := <-messageChannel:
			// 给在线的用户发送消息
			for user := range users {
				user.MessageChannel <- msg
			}
		}
	}

}
  • 处理用户连接和发送消息方法
func handleConn(conn net.Conn) {
	defer conn.Close()
	// 新用户进来创建实例
	user := &User{
		ID:             int(time.Now().Unix()),
		Addr:           conn.RemoteAddr().String(),
		EnterAt:        time.Now(),
		MessageChannel: make(chan string, 8),
	}
	// 由于当前是在一个新的goroutine中进行的,所以需要开一个goroutine用于写操作
	go sendMessage(conn, user.MessageChannel)

	// 给当前用户发送欢迎消息
	user.MessageChannel <- "welcome, " + user.Addr
	messageChannel <- "user:`" + strconv.Itoa(user.ID) + "`has enter"

	// 记录到全局用户列表中,避免用锁
	enteringChannel <- user

	//循环读取用户输入
	input := bufio.NewScanner(conn)

	for input.Scan() {
		messageChannel <- strconv.Itoa(user.ID) + ":" + input.Text()
	}
	if err := input.Err(); err != nil {
		log.Println("读取错误:", err)

	}

	leavingChannel <- user
	messageChannel <- "user:`" + strconv.Itoa(user.ID) + "`has left"

}
  • 主函数方法
func main() {
	// 简历tcp连接
	lintener, err := net.Listen("tcp", ":9090")
	if err != nil {
		panic(err)
	}
	// 调用广播来监听
	go broadcaster()

	for {
		conn, err := lintener.Accept()

		if err != nil {
			log.Println(err)
			continue

		}
		// 处理连接请求
		go handleConn(conn)

	}
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值