golang的socket的群聊

在前面2篇的文章,我们一直说的是一个客户端和一个服务的端的交互模式,现在我们来说下群聊模式,即多个客户端和一个服务端的交互模式,关键的知识点在于服务端如何转发消息。

我们现在通过一个map来存储所有的连接,然后通过遍历map来对所有连接发消息,代码如下:

package main

/*
* 群聊--广播消息
 */

import (
	"bufio"
	"fmt"
	"math/rand"
	"net"
	"strings"
	"sync"
	"time"
)

//保存连接
var connList sync.Map

//随机字符串
func randName() string {
	var letterRunes = []rune("123456789")
	rand.Seed(time.Now().UnixNano())
	b := make([]rune, 6)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func DealConn(conn net.Conn) {
	// 处理完关闭连接
	defer conn.Close()
	fmt.Println("new conn\n")
	name := randName()
	connList.Store(name, conn)
	conn.Write([]byte("you is  : " + name + "\r\n"))
	// 针对当前连接做发送和接受操作
	for {
		reader := bufio.NewReader(conn)
		// 读取字符串, 直到碰到回车返回
		str, err := reader.ReadString('\n')
		// 数据读取正确
		if err == nil {
			// 去掉字符串尾部的回车
			str = strings.TrimSpace(str)
			//广播消息
			connList.Range(func(k, userConn interface{}) bool {
				userConn.(net.Conn).Write([]byte(" say : " + str + "\r\n"))
				return true
			})
		} else {
			//删除保存的连接
			connList.Delete(name)
			fmt.Println("conn close\n")
			break
		}
	}
}

func main() {
	// 建立tcp 服务
	listen, err := net.Listen("tcp", "0.0.0.0:1215")
	if err != nil {
		fmt.Printf("listen failed, err:%v\n", err)
		return
	}

	for {
		// 等待客户端建立连接
		fmt.Printf("accept conn ...... \n")
		conn, err := listen.Accept()
		if err != nil {
			fmt.Printf("accept failed, err:%v\n", err)
			continue
		}

		// 启动一个单独的 goroutine 去处理连接
		go DealConn(conn)
	}
}

启动上面的代码做服务端,然后通过启动多个telnet,就可以发现,每个telnet端发的消息,其他telnet也可以收到.

此条目发表在 好文推荐 分类目录,贴了 标签。将固定链接加入收藏夹。

golang的socket的群聊》有 1 条评论

  1. xtgxiso 说:

    一般群的相关信息都维护在DB中,发群消息的时候通过群ID来获取群成员,然后再发给群成员