基于websocket的聊天室,可进一步参考:
(2) Golang代码搜集-基于websocket+vue.js的简易聊天室
闲着无聊ing~
一直想着能用go整一些好玩的小工具,想着想着突然想到实现一个简易的群聊工具,然后看了上面几个大佬文章,边看边动手实现下...
聊天室的组成
聊天室分为两个部分,分别是:
- 服务端
- 客户端
然后,一般情况下我们互相聊天使用的都只是客户端而已,服务端只是起到调度的作用。
信息发送与接收的流程
假设我们有 服务端(S) 客户端(C1) 客户端(C2) 客户端(C3)并且 S 已经 与 C1 C2 C3 建立了连接。
理论上的流程是这样的:
- C1 向 S 发出信息
- S 接收到信息
- S 将接收到的信息广播给 C2 C3
- C2 C3 接收信息
服务端代码
packagemainimport ( "fmt""net""time") // 客户端 mapvarclientMap=make(map[string]*net.TCPConn) // 存储当前群聊中所有用户连接信息:key: ip+port, val: 用户连接信息// 监听请求funclistenClient(ipAndPortstring) { tcpAddr, _ :=net.ResolveTCPAddr("tcp", ipAndPort) tcpListener, _ :=net.ListenTCP("tcp", tcpAddr) for { // 循环接收clientConn, _ :=tcpListener.AcceptTCP() // 监听请求连接clientMap[clientConn.RemoteAddr().String()] =clientConn// 将连接添加到 mapgoaddReceiver(clientConn) fmt.Println("用户 : ", clientConn.RemoteAddr().String(), " 已连接.") } } // 向连接添加接收器funcaddReceiver(newConnect*net.TCPConn) { for { byteMsg :=make([]byte, 2048) len, err :=newConnect.Read(byteMsg) // 从newConnect中读取信息到缓存中iferr!=nil { newConnect.Close() } fmt.Println(string(byteMsg[:len])) msgBroadcast(byteMsg[:len], newConnect.RemoteAddr().String()) } } // 广播给所有 clientfuncmsgBroadcast(byteMsg []byte, keystring) { fork, con :=rangeclientMap { ifk!=key { // 转发消息给当前群聊中,除自身以外的其他用户con.Write(byteMsg) } } } // 初始化funcinitGroupChatServer() { fmt.Println("服务已启动...") time.Sleep(1*time.Second) fmt.Println("等待客户端请求连接...") golistenClient("127.0.0.1:1801") select {} } funcmain() { initGroupChatServer() }
客户端代码
packagemainimport ( "bufio""fmt""net""os") // 用户名varloginNamestring// 本机连接varselfConnect*net.TCPConn// 读取行文本varreader=bufio.NewReader(os.Stdin) // 建立连接funcconnect(addrstring) { tcpAddr, _ :=net.ResolveTCPAddr("tcp", addr) // 使用tcpcon, err :=net.DialTCP("tcp", nil, tcpAddr) // 拨号:主动向server建立连接selfConnect=coniferr!=nil { fmt.Println("连接服务器失败") os.Exit(1) } gomsgSender() gomsgReceiver() } // 消息接收器funcmsgReceiver() { buff :=make([]byte, 2048) for { len, _ :=selfConnect.Read(buff) // 从建立连接的缓冲区读消息fmt.Println(string(buff[:len])) } } // 消息发送器funcmsgSender() { for { bMsg, _, _ :=reader.ReadLine() bMsg= []byte(loginName+" : "+string(bMsg)) selfConnect.Write(bMsg) // 发消息 } } // 初始化funcinitGroupChatClient() { fmt.Println("请问您怎么称呼?") bName, _, _ :=reader.ReadLine() loginName=string(bName) connect("127.0.0.1:1801") select {} } funcmain() { initGroupChatClient() }
运行结果展示:
server端:
编辑
client端:
编辑