Go语言聊天室demo
- 话不多说直接上代码
话不多说直接上代码
Tcp服务端
package mainimport ("container/list""encoding/json""fmt"uuid "github.com/satori/go.uuid""net""strings"
)type GlobalConnInfo struct {ClientConnMap map[string]net.ConnClientList list.List
}type RespModel struct {Code intMsg stringData any
}func main() {//这里维护了客户客户端的连接信息globalConnInfo := GlobalConnInfo{ClientConnMap: make(map[string]net.Conn), ClientList: list.List{}}//监听端口listener, _ := net.Listen("tcp", ":9876")fmt.Println("TCP服务器启动监听")for {//Listen返回成功后,这个服务会进入一个循环,调用net.Listener 的 Accept 方法接收新客户端连接//在没有新连接的时候,这个服务会阻塞在 Accept 调用上,直到有客户端连接上来,Accept 方法将返回一个 net.Conn 实例,用于和新连上的客户端进行通信。conn, _ := listener.Accept()fmt.Println("【新的连接上来了, 启动新的协程处理】", conn)//启动go协程, 处理conn的逻辑go doSyncHandler(conn, globalConnInfo)}
}func doSyncHandler(conn net.Conn, globalConnInfo GlobalConnInfo) {//重命名函数name := serverFirstRename(conn)//将name作为key维护连接globalConnInfo.ClientConnMap[name] = connglobalConnInfo.ClientList.PushBack(name)//核心交互逻辑for {//定义读取数据读缓存数组var readBytes []byte = make([]byte, 1024)size, _ := conn.Read(readBytes)//客户端给服务器发了数据服务端才返回if size >= 0 {action := strings.TrimSpace(string(readBytes))[:size]fmt.Println("【server】[client ---> server] : ", action)if action == "1" {resultBytes, _ := json.Marshal(RespModel{Code: 200, Msg: "当前系统在线用户", Data: globalConnInfo})conn.Write(resultBytes)} else if action == "2" {resultBytes, _ := json.Marshal(RespModel{Code: 200, Msg: "新用户昵称", Data: uuid.NewV1().String()[:32]})conn.Write(resultBytes)} else if action == "3" {resultBytes, _ := json.Marshal(RespModel{Code: 200, Msg: "退出成功", Data: nil})conn.Write(resultBytes)} else {resultBytes, _ := json.Marshal(RespModel{Code: 200, Msg: "暂未开发的操作, 请重新选择操作", Data: nil})conn.Write(resultBytes)}}}}func serverFirstRename(conn net.Conn) string {//服务端随机命名var name string = uuid.NewV1().String()[:32]//返回服务端命名结果firstWriteBytes := []byte(name)conn.Write(firstWriteBytes)fmt.Println("【server】[server ---> client] 服务端命名结果: ", string(firstWriteBytes))return name
}
Tcp客户端
package mainimport ("bufio""fmt""net""os""strings"
)type RespModel struct {Code intMsg stringData any
}func main() {scanner := bufio.NewScanner(os.Stdin)//Dial 函数向服务端发起 TCP 连接,这个函数会一直阻塞,直到连接成功或失败后,才会返回。conn, _ := net.Dial("tcp", "localhost:9876")fmt.Println("【客户端监听服务】")//客户端命名clientFirstRename(conn)for {//控制台读取fmt.Println("您可以选择操作: 1.聊天, 2.系统重命名, 3.退出聊天室", actionMap)scanner.Scan()//定义写入缓存数组writeBytes := []byte(strings.TrimSpace(scanner.Text()))conn.Write(writeBytes)fmt.Println("【client】[client ---> server] : ", string(writeBytes))//定义读取数据读缓存数组var readBytes []byte = make([]byte, 1024)conn.Read(readBytes)fmt.Println("【client】[server ---> client] : ", string(readBytes))}}func clientFirstRename(conn net.Conn) {//定义读取数据读缓存数组var readBytes []byte = make([]byte, 1024)conn.Read(readBytes)fmt.Println("【client】[server ---> client] 来自服务端的名称:", string(readBytes))
}