Go语言聊天室demo

Go语言聊天室demo

话不多说直接上代码

Tcp服务端

package main

import (
	"container/list"
	"encoding/json"
	"fmt"
	uuid "github.com/satori/go.uuid"
	"net"
	"strings"
)

type GlobalConnInfo struct {
	ClientConnMap map[string]net.Conn
	ClientList    list.List
}

type RespModel struct {
	Code int
	Msg  string
	Data 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] = conn
	globalConnInfo.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 main

import (
	"bufio"
	"fmt"
	"net"
	"os"
	"strings"
)

type RespModel struct {
	Code int
	Msg  string
	Data 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))
}

相关推荐

  1. Go语言聊天demo

    2024-03-11 13:34:06       20 阅读
  2. NIO案例-聊天

    2024-03-11 13:34:06       33 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-11 13:34:06       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-11 13:34:06       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-11 13:34:06       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-11 13:34:06       20 阅读

热门阅读

  1. 【golang】二叉树的遍历

    2024-03-11 13:34:06       22 阅读
  2. Go语法之函数 defer使用

    2024-03-11 13:34:06       20 阅读
  3. 大数据开发(Hadoop面试真题-卷六)

    2024-03-11 13:34:06       24 阅读
  4. Node.js概述与安装和运行

    2024-03-11 13:34:06       20 阅读
  5. springboot文件上传

    2024-03-11 13:34:06       20 阅读
  6. 《Webpack 报错》Can‘t find stylesheet to import

    2024-03-11 13:34:06       22 阅读
  7. 程序员如何选择职业赛道?

    2024-03-11 13:34:06       26 阅读
  8. 微服务面试题

    2024-03-11 13:34:06       22 阅读
  9. (C++) 如何设计一个安全的pop函数

    2024-03-11 13:34:06       23 阅读