go消息服务器,GO 并发聊天服务器

package main

import (

"fmt"

"net"

"strings"

"time"

)

// 用户结构体

type Client struct {

C chan string //用户发送数据的管道

Name string // 用户名

Addr string // 网络地址

}

// 保存在线用户

var onlineMap map[string]Client

// 通讯的管道

var message = make(chan string)

func main() {

//1. 监听

listener, err := net.Listen("tcp", "127.0.0.1:888")

if err != nil {

fmt.Println("net.Listen:", err)

return

}

defer listener.Close()

// 新开一个协成,转发消息,只要有消息来了就遍历map发消息

go Manager()

//2. 主协成,阻塞等待用户

for {

conn, err := listener.Accept()

if err != nil {

fmt.Println("listener.Accept:", err)

continue //记住

}

// 处理用户连接

go HandleConn(conn)

}

}

//处理用户连接

func HandleConn(conn net.Conn) {

defer conn.Close()

// 获取用户地址

cliAddr := conn.RemoteAddr().String()

// 创建一个结构体

cli := Client{make(chan string), cliAddr, cliAddr}

// 结构体添加到map

onlineMap[cliAddr] = cli

// 新开一个协成,专门给当前客户端发送信息

go WriteMsgToClient(cli, conn)

// 广播某个用户在线

message

// 提示我是谁

cli.C

//定义一个管道判断是否主动退出

isQuit := make(chan bool)

//定义一个通道判断是否超时

isTimeOut := make(chan bool)

// 新开一个协成,接受用户发送过来的数据

go func() {

buf := make([]byte, 1024*2)

for {

n, err := conn.Read(buf)

if n == 0 { // 对方断开

isQuit

fmt.Println("conn.Read:", err)

return

}

// 获取用户信息

userMsg := string(buf[:n-1]) // windows nc测试多个换行

// 处理字符

if len(userMsg) == 3 && userMsg == "who" {

//遍历map给当前用户发送所有成员

conn.Write([]byte("user list:\n"))

for _, tmp := range onlineMap {

userMsg = tmp.Addr + ":" + tmp.Name + "\n"

conn.Write([]byte(userMsg))

}

} else if len(userMsg) >= 8 && userMsg[:6] == "rename" {

// rename|yoyo

name := strings.Split(userMsg, "|")[1] //窃取后面一个

//重新复制

cli.Name = name

onlineMap[cliAddr] = cli

//广播给自己

cli.C

} else {

// 转发此内容

message

}

// 进来这里就有数据不超时

isTimeOut

}

}()

for {

// 通过select检车channel流动

select {

case

delete(onlineMap, cliAddr) //移除当前用户

message

return

case

case

delete(onlineMap, cliAddr)

message

return

}

}

}

func Manager() {

// 给map分配空间

onlineMap = make(map[string]Client)

for {

msg :=

// 遍历map给每个成员发消息

for _, cli := range onlineMap {

cli.C

}

}

}

// 给当前发送消息

func WriteMsgToClient(cli Client, conn net.Conn) {

// 给当前客服端发送信息

for msg := range cli.C {

conn.Write([]byte(msg + "\n"))

}

}

// 制作格式字符串

func MakeStr(cli Client, str string) string {

return "[" + cli.Addr + "]" + cli.Name + ":" + str

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值