您的位置:首页 > 理论基础 > 计算机网络

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

2015-06-02 00:00 666 查看

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

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

服务端的改动

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

var ConnMap map[string]*net.TCPConn

接着, 每次当有新的客户端连接到服务器时, 需要把这个客户端连接行信息加入集合:

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

当服务器收到客户端的聊天信息时, 需要广播到所有客户端, 所以我们需要利用上面保存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端, 然后新开两个个终端, 启动客户端, 在其中一个客户端里键入聊天信息后回车, 会发现另外一个客户端收到了刚刚发送的聊下天信息

完事大吉!

相关源码:
https://git.oschina.net/victoriest/go-simple-tcp-server.git
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息