go语言如何实现即时通讯聊天室
发表于:2025-11-07 作者:千家信息网编辑
千家信息网最后更新 2025年11月07日,本文小编为大家详细介绍"go语言如何实现即时通讯聊天室",内容详细,步骤清晰,细节处理妥当,希望这篇"go语言如何实现即时通讯聊天室"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知
千家信息网最后更新 2025年11月07日go语言如何实现即时通讯聊天室
本文小编为大家详细介绍"go语言如何实现即时通讯聊天室",内容详细,步骤清晰,细节处理妥当,希望这篇"go语言如何实现即时通讯聊天室"文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
实现的功能:公聊,私聊,修改用户名
只用到了四个类:
main.go:用来启动服务器
server.go:服务器相关代码
client.go:客户端相关代码,用户可以直接操作的可视化界面
user.go:用户类,用来封装用户的业务逻辑
架构图
完整代码
server.go
package mainimport ( "fmt" "io" "net" "sync" "time")type Server struct { Ip string Port int //在线用户列表 OnlineMap map[string]*User mapLock sync.RWMutex //消息广播的Channel Message chan string}func NewServer(ip string, port int) *Server { server := &Server{ Ip: ip, Port: port, OnlineMap: make(map[string]*User), Message: make(chan string), } return server}func (s *Server) Handler(conn net.Conn) { //业务逻辑 //fmt.Println("链接建立成功") user := NewUser(conn, s) user.Online() //监听用户是否活跃 isLive := make(chan bool) go func() { buf := make([]byte, 4096) for { n, error := conn.Read(buf) if n == 0 { user.Offline() return } if error != nil && error != io.EOF { fmt.Println("read error") } msg := string(buf[:n-1]) user.DoMessage(msg) //表示用户活跃 isLive <- true } }() for { select { case <-isLive: //当前用户活跃,不做任何时,激活select,重置定时器 case <-time.After(time.Second * 300): //超时,将user强制关闭 user.SendMsg("你被踢了") close(user.C) conn.Close() return } }}func (s *Server) ListenMessager() { for { msg := <-s.Message s.mapLock.Lock() for _, user := range s.OnlineMap { user.C <- msg } s.mapLock.Unlock() }}func (s *Server) BroadCast(user *User, msg string) { sendMsg := "[" + user.Addr + "]" + user.Name + ":" + msg s.Message <- sendMsg}func (s *Server) Start() { listener, error := net.Listen("tcp", fmt.Sprintf("%s:%d", s.Ip, s.Port)) if error != nil { fmt.Println("listener error...") return } defer listener.Close() go s.ListenMessager() for { conn, error := listener.Accept() if error != nil { fmt.Println("accept error...") continue } go s.Handler(conn) }}client.go
package mainimport ( "flag" "fmt" "io" "net" "os")type Client struct { ServerIp string ServerPort int Name string conn net.Conn flag int}func NewClient(serverIp string, serverPort int) *Client { client := &Client{ ServerIp: serverIp, ServerPort: serverPort, flag: 9999, } conn, error := net.Dial("tcp", fmt.Sprintf("%s:%d", serverIp, serverPort)) if error != nil { fmt.Println("net dial error...") return nil } client.conn = conn return client}func (c *Client) menu() bool { var flag int fmt.Println("1.公聊模式") fmt.Println("2.私聊模式") fmt.Println("3.修改用户名") fmt.Println("0.退出") fmt.Scanln(&flag) if flag >= 0 && flag <= 3 { c.flag = flag return true } else { fmt.Println(">>>>请输入合法数字<<<<") return false }}//修改用户名func (c *Client) UpdateName() bool { fmt.Println(">>>>请输入用户名") fmt.Scanln(&c.Name) sendMsg := "rename|" + c.Name + "\n" _, error := c.conn.Write([]byte(sendMsg)) if error != nil { fmt.Println("conn.write error...") return false } return true}//公聊func (c *Client) PublicChat() { var chatMsg string fmt.Println(">>>>请输入聊天内容,输入exit退出") fmt.Scanln(&chatMsg) for chatMsg != "exit" { if len(chatMsg) != 0 { msg := chatMsg + "\n" _, error := c.conn.Write([]byte(msg)) if error != nil { fmt.Println("conn.Write error....") break } } chatMsg = "" fmt.Println(">>>>请输入聊天内容,输入exit退出") fmt.Scanln(&chatMsg) }}//私聊func (c *Client) PrivateChat() { var remoteUser string var chatMsg string c.SelectUsers() fmt.Println(">>>>请输入聊天对象的用户名,输入exit退出") fmt.Scanln(&remoteUser) for remoteUser != "exit" { fmt.Println(">>>>请输入聊天内容,输入exit退出") fmt.Scanln(&chatMsg) for chatMsg != "exit" { if len(chatMsg) != 0 { msg := "to|" + remoteUser + "|" + chatMsg + "\n\n" _, error := c.conn.Write([]byte(msg)) if error != nil { fmt.Println("conn.Write error....") break } } chatMsg = "" fmt.Println(">>>>请输入聊天内容,输入exit退出") fmt.Scanln(&chatMsg) } c.SelectUsers() remoteUser = "" fmt.Println(">>>>请输入聊天对象的用户名,输入exit退出") fmt.Scanln(&remoteUser) }}//查询在线用户func (c *Client) SelectUsers() { sendMsg := "who\n" _, error := c.conn.Write([]byte(sendMsg)) if error != nil { fmt.Println("conn.Write error....") return }}//处理server返回的消息func (c *Client) DealResponse() { io.Copy(os.Stdout, c.conn)}func (c *Client) Run() { for c.flag != 0 { for c.menu() != true { } switch c.flag { case 1: //公聊 c.PublicChat() case 2: //私聊 c.PrivateChat() case 3: //修改用户名 c.UpdateName() } }}var serverIp stringvar serverPort intfunc init() { flag.StringVar(&serverIp, "ip", "127.0.0.1", "设置服务器IP地址(默认为127.0.0.1)") flag.IntVar(&serverPort, "port", 8888, "设置服务器端口(默认为8888)")}func main() { flag.Parse() client := NewClient(serverIp, serverPort) if client == nil { fmt.Println(">>>>链接服务器失败") return } go client.DealResponse() fmt.Println(">>>>链接服务器成功") client.Run()}user.go
package mainimport ( "net" "strings")type User struct { Name string Addr string C chan string conn net.Conn server *Server}func NewUser(conn net.Conn, server *Server) *User { userAddr := conn.RemoteAddr().String() user := &User{ Name: userAddr, Addr: userAddr, C: make(chan string), conn: conn, server: server, } go user.ListenMessage() return user}//用户上线func (u *User) Online() { u.server.mapLock.Lock() u.server.OnlineMap[u.Name] = u u.server.mapLock.Unlock() u.server.BroadCast(u, "上线")}//用户下线func (u *User) Offline() { u.server.mapLock.Lock() delete(u.server.OnlineMap, u.Name) u.server.mapLock.Unlock() u.server.BroadCast(u, "下线")}//给当前user的客户端发送消息func (u *User) SendMsg(msg string) { u.conn.Write([]byte(msg))}//处理消息func (u *User) DoMessage(msg string) { if msg == "who" { //查询当前在线用户 u.server.mapLock.Lock() for _, user := range u.server.OnlineMap { onlineMsg := "[" + user.Addr + "]" + user.Name + ":在线...\n" u.SendMsg(onlineMsg) } u.server.mapLock.Unlock() } else if len(msg) > 7 && msg[:7] == "rename|" { //修改用户名 rename|xxx newName := strings.Split(msg, "|")[1] //判断名字是否已经存在 _, ok := u.server.OnlineMap[newName] if ok { u.SendMsg("用户名已存在\n") } else { u.server.mapLock.Lock() delete(u.server.OnlineMap, u.Name) u.server.OnlineMap[newName] = u u.server.mapLock.Unlock() u.Name = newName u.SendMsg("用户名成功修改为:" + newName + "\n") } } else if len(msg) > 4 && msg[:3] == "to|" { //私聊 to|zhangsan|你好 //获取对方用户名 remoteName := strings.Split(msg, "|")[1] if remoteName == "" { u.SendMsg("用户名格式不对\n") return } //获取对方user remoteUser, ok := u.server.OnlineMap[remoteName] if !ok { u.SendMsg("用户不存在\n") return } //获取消息 msg := strings.Split(msg, "|")[2] if msg == "" { u.SendMsg("无消息内容,重新发送\n") } //发送消息 remoteUser.SendMsg(u.Name + "对您说:" + msg) } else { u.server.BroadCast(u, msg) }}func (u *User) ListenMessage() { for { msg := <-u.C u.conn.Write([]byte(msg + "\n")) }}main.go
package mainfunc main() { server := NewServer("127.0.0.1", 8888) server.Start()}读到这里,这篇"go语言如何实现即时通讯聊天室"文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注行业资讯频道。
用户
输入
用户名
内容
消息
服务器
服务
在线
聊天室
语言
通讯
成功
代码
文章
链接
处理
下线
业务
客户
客户端
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
手机网吧服务器怎么改家用
网络技术竞赛复试题
网络服务器配置与管理期末考试
堡垒机和数据库审计
造价项目管理软件开发
虚拟服务器app怎么下载
辽宁省公安厅网络安全科
8xln服务器
知网 数据库光盘
万方数据库下的论文
数据库如何插入数据和换位置
购买数据库缴纳什么增值税
网络安全毕业设计教学视频
教育系统网络安全管理总结
p2p网络技术书籍
zabbix跳过数据库
计算机网络移动终端软件开发
华为服务器安全防护卡
深圳新学道互联网教育科技
服务器懒人包
数据库网站的搭建
win20服务器配置
linux服务器宕机只有重启吗
东莞清吧会员系统软件开发
软件开发员工考核
腾讯云服务器管理
软件开发报价每日费用
洛阳市翔度网络技术有限公司
网络技术在校园网中的应用
学习网络安全工程师用什么软件