分享
  1. 首页
  2. 文章

Golang实现简单tcp服务器03 -- 文本广播式聊天服务器/客户端

victoriest · · 5196 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

用Golang实现 文本广播式聊天服务器/客户端

本节, 我们将一步一步的把上一节完成的echo服务器/客户端改造成一个文本信息的聊天室

服务端的改动

  1. 服务器为了实现聊天信息的群体广播, 需要记录所有连接到服务器的客户端信息, 所以, 我们需要添加一个集合来保存所有客户端的连接:

    var ConnMap map[string]*net.TCPConn
  2. 接着, 每次当有新的客户端连接到服务器时, 需要把这个客户端连接行信息加入集合:

    ConnMap[tcpConn.RemoteAddr().String()] = tcpConn

  3. 当服务器收到客户端的聊天信息时, 需要广播到所有客户端, 所以我们需要利用上面保存TCPConn的map来遍历所有TCPConn进行广播, 用以下方法实现:

    func boradcastMessage(message string) {
     b := []byte(message)
     for _, conn := range ConnMap {
     conn.Write(b)
     }
    }
    

客户端代码改动

客户端代码改动相对简单, 只是加入了用户自己输入聊天信息的功能, 在连接成功并且 启动了消息接收的gorountine后, 加入以下代码:

 for {
 var msg string
 fmt.Scanln(&msg)
 if msg == "quit" {
 break
 }
 b := []byte(msg + "\n")
 conn.Write(b)
 }

完整的服务端代码如下:

server.go

package main
import (
 "bufio"
 "fmt"
 "net"
)
// 用来记录所有的客户端连接
var ConnMap map[string]*net.TCPConn
func main() {
 var tcpAddr *net.TCPAddr
 ConnMap = make(map[string]*net.TCPConn)
 tcpAddr, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:9999")
 tcpListener, _ := net.ListenTCP("tcp", tcpAddr)
 defer tcpListener.Close()
 for {
 tcpConn, err := tcpListener.AcceptTCP()
 if err != nil {
 continue
 }
 fmt.Println("A client connected : " + tcpConn.RemoteAddr().String())
 // 新连接加入map
 ConnMap[tcpConn.RemoteAddr().String()] = tcpConn
 go tcpPipe(tcpConn)
 }
}
func tcpPipe(conn *net.TCPConn) {
 ipStr := conn.RemoteAddr().String()
 defer func() {
 fmt.Println("disconnected :" + ipStr)
 conn.Close()
 }()
 reader := bufio.NewReader(conn)
 for {
 message, err := reader.ReadString('\n')
 if err != nil {
 return
 }
 fmt.Println(conn.RemoteAddr().String() + ":" + string(message))
 // 这里返回消息改为了广播
 boradcastMessage(conn.RemoteAddr().String() + ":" + string(message))
 }
}
func boradcastMessage(message string) {
 b := []byte(message)
 // 遍历所有客户端并发送消息
 for _, conn := range ConnMap {
 conn.Write(b)
 }
}

客户端完整代码如下:

client.go

package main
import (
 "bufio"
 "fmt"
 "net"
)
func main() {
 var tcpAddr *net.TCPAddr
 tcpAddr, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:9999")
 conn, _ := net.DialTCP("tcp", nil, tcpAddr)
 defer conn.Close()
 fmt.Println("connected!")
 go onMessageRecived(conn)
 // 控制台聊天功能加入
 for {
 var msg string
 fmt.Scanln(&msg)
 if msg == "quit" {
 break
 }
 b := []byte(msg + "\n")
 conn.Write(b)
 }
}
func onMessageRecived(conn *net.TCPConn) {
 reader := bufio.NewReader(conn)
 for {
 msg, err := reader.ReadString('\n')
 fmt.Println(msg)
 if err != nil {
 quitSemaphore <- true
 break
 }
 }
}

最后分别编译server与client试试效果吧!

go build server.go

go build client.go

先启动server端, 然后新开两个个终端, 启动客户端, 在其中一个客户端里键入聊天信息后回车, 会发现另外一个客户端收到了刚刚发送的聊下天信息

完事大吉!


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
5196 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏