Go语言之TCP聊天室
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Go语⾔之TCP聊天室服务端流程图如下:
package main
import (
"fmt"
"net"
)
// 客户端结构体
type Client struct {
//⽤户通信
C chan string
//客户端名称
name string
//客户端地址
addr string
}
//map存储在线⽤户
var is_online map[string]Client
//消息通讯
var messages = make(chan string)
//⼴播全局消息到客户端
func Message() {
is_online = make(map[string]Client)
// 循环读取 message 通道中的数据
for {
// 通道 message 中有数据读到 msg 中。
没有,则阻塞
msg := <-messages
// ⼀旦执⾏到这⾥,说明message中有数据了,解除阻塞。
遍历 map
for _, client := range is_online {
client.C <- msg // 把从Message通道中读到的数据,写到 client 的 C 通道中。
}
}
}
//⽣产消息函数
func MakeMsg(client Client, msg string) (buf string) {
buf = "[" + client.addr + "]" + + ": " + msg
return
}
//发送消息给在线客户端
func WriteMsgToClient(conn net.Conn, client Client) {
for msg := range client.C {
conn.Write([]byte(msg))
}
}
func Handler(conn net.Conn) {
//把当前客户端添加到在线map中
addr := conn.RemoteAddr().String()
client := Client{make(chan string), addr, addr}
//将当前客户端加⼊在线字典列表中
is_online[addr] = client
//创建⼀个协程,专门给当前客户端发消息
go WriteMsgToClient(conn, client)
//将⽤户上线的消息放到全局消息中
messages <- MakeMsg(client, "login")
// 创建⼀个新协程,循环读取⽤户发送的消息,⼴播给在线⽤户
go func() {
for {
buf := make([]byte, 2048)
//读取客户端数据
n, _ := conn.Read(buf)
if n == 0 {
fmt.Printf("⽤户%s退出登录\n", )
//将当前⽤户从在线字典中删除
delete(is_online, addr)
//通知其他客户端该⽤户退出登录
messages <- MakeMsg(client, "logout") return
}
msg := string(buf[:n])
//将客户端发的消息加⼊到全局消息通道中 messages <- MakeMsg(client, msg)
}
}()
//让协程不停⽌运⾏
for {
}
}
func main() {
//奖励tcp监听
listen, err := net.Listen("tcp", ":8000")
if err != nil {
fmt.Println(err.Error())
return
}
defer listen.Close()
//创建协程处理消息
go Message()
for {
//阻塞等待客户端连接
conn, err := listen.Accept()
if err != nil {
fmt.Println(err.Error())
}
//创建协程处理客户端事件
go Handler(conn)
defer conn.Close()
}
}
效果图如下:。