GO网络编程(五):海量用户通信系统3:整体框架与C/S通信总体流程【重要】

这个系统其实是尚硅谷的老韩讲的(尚硅谷网络编程项目),但是他讲得很碎片化,思路不够清晰,时间又长,所以要掌握还是挺难的。如果你听了他的视频,不去梳理系统业务流程,不去看代码就往下听,那是很容易懵圈的。好在本人做了登录模块和服务器处理消息的业务流程图,我相信这一定有助于大家整理思路和理解系统业务流程。另外,因为老韩之后把login函数的部分代码封装到单独的包里了,所以我就干脆从头开始快速讲一遍,当然之前讲过的知识不会再讲。

目录

    • 一、系统框架搭建
    • 二、C/S通信总体流程
      • 1.登录模块总体流程
      • 2.服务器处理消息总体流程

一、系统框架搭建

首先我们需要搭建好目录结构,目录结构如下

海量用户通信系统/
├── go.mod
├── client/
│   ├── main.go
│   └── login.go
├── server/
│   └── main.go
└── common/├── message/│   └── message.go└── utils/└── utils.go

注意,模块名需要自定义,我的模块名叫MassUsrsCom。搭建好后,按如下步骤构建初步的代码:
1.在message.go中定义消息类型

package messageconst (LoginMesType    = "LoginMes"LoginResMesType = "LoginResMes"RegisterMesType = "RegisterMes"
)type Message struct {Type string `json:"type"` //消息类型Data string `json:"data"` //消息
}// 定义两个消息..后面需要再增加
type LoginMes struct {UserID   int    `json:"userID"`   //用户idUserPwd  string `json:"userPwd"`  //用户密码UserName string `json:"userName"` //用户名
}type LoginResMes struct {Code  int    `json:"code"`  //返回状态码 500表示该用户未注册 200表示登录成功Error string `json:"error"` //返回错误信息
}
type RegisterMes struct {
}

2.在utils.go中声明读数据包和写数据包的函数

package utilsimport ("MassUsrsCom/common/message""encoding/binary""encoding/json""fmt""net"
)// 读数据包
func ReadPkg(conn net.Conn) (mes message.Message, err error) {return
}// 写数据包
func WritePkg(conn net.Conn, data []byte) (err error) {return
}

3.在login.go中声明 login函数

package mainimport ("MassUsrsCom/common/message""MassUsrsCom/common/utils""encoding/json""fmt""net"
)func login(userID int, userPwd string) (err error) {return
}

4.在client包的main.go中写完整的代码

package mainimport ("fmt"
)// 定义两个变量,一个表示用户id,一个表示用户密码
var userID int
var userPwd stringfunc main() {//接收用户的选择var key int//判断是否还继续显示菜单var loop = truefor loop {fmt.Println("------------------欢迎登录多人聊天系统")fmt.Println("\t\t\t 1 登录聊天室")fmt.Println("\t\t\t 2 注册用户")fmt.Println("\t\t\t 3 退出系统")fmt.Println("\t\t\t 请选择(1-3):")fmt.Scanln(&key)switch key {case 1:fmt.Println("登录聊天室")loop = falsecase 2:fmt.Println("注册用户")loop = falsecase 3:fmt.Println("退出系统")loop = falsedefault:fmt.Println("你的输入有误,请重新输入")}}//根据用户输入显示新的提示信息if key == 1 {//说明用户要登录fmt.Printf("请输入用户的id号:")fmt.Scanf("%d\n", &userID)fmt.Printf("请输入用户的密码:")fmt.Scanf("%s\n", &userPwd)login(userID, userPwd)} else if key == 2 {fmt.Println("进行用户注册的逻辑...")}
}

5.在server包的main.go中写部分代码

package mainimport ("MassUsrsCom/common/message""MassUsrsCom/common/utils""encoding/json""fmt""io""net"
)// 处理登录消息
func serverProcessLogin(conn net.Conn, mes *message.Message) (err error) {return
}// 判断并处理不同种类的消息
func serverProcessMes(conn net.Conn, mes *message.Message) (err error) {switch mes.Type {case message.LoginMesType://处理登录逻辑err = serverProcessLogin(conn, mes)case message.RegisterMesType://处理注册default:fmt.Println("消息类型不存在,无法处理...")}return
}// 处理和客户端的通信
func process(conn net.Conn) {
}
func main() {
}

二、C/S通信总体流程

1.登录模块总体流程

流程图
在这里插入图片描述

代码

func login(userID int, userPwd string) (err error) {//下一个就要开始定协议// fmt.Printf("userId=%d pwd=%s\n", userId, pwd)// return nil//1.连接到服务器conn, err := net.Dial("tcp", "localhost:8889")if err != nil {fmt.Println("net.Dial error:", err)return}//延时关闭defer conn.Close()//2.初始化一个Mes 结构体var mes message.Messagemes.Type = message.LoginMesType//3.初始化一个LoginMes 结构体var loginMes message.LoginMesloginMes.UserID = userIDloginMes.UserPwd = userPwd//4.将loginMes 序列化data, err := json.Marshal(loginMes)if err != nil {fmt.Println("json.Marshal error:", err)return}//5.将序列化后的loginMes作为mes的Data部分mes.Data = string(data)//6.将mes序列化data, err = json.Marshal(mes)if err != nil {fmt.Println("json.Marshal error:", err)return}//7.发送消息,即mes的Data部分err = utils.WritePkg(conn, data)if err != nil {fmt.Println("WritePkg(conn) error:", err)return}//8.接收服务器端返回的信息(消息mes或错误)mes, err = utils.ReadPkg(conn) //mesif err != nil {fmt.Println("ReadPkg(conn) error:", err)return}//9.将mes的Data部分反序列化成LoginResMesvar loginResMes message.LoginResMeserr = json.Unmarshal([]byte(mes.Data), &loginResMes)if err != nil {fmt.Println("json.Unmarshal error:", err)return}//10.验证LoginResMesif loginResMes.Code == 200 {fmt.Println("登录成功")} else if loginResMes.Code == 500 {fmt.Println(loginResMes.Error)}return
}

2.服务器处理消息总体流程

流程图
在这里插入图片描述

代码

// 处理和客户端的通信
func process(conn net.Conn) {//这里需要延时关闭conndefer conn.Close()//循环读取客户端发送的信息for {mes, err := utils.ReadPkg(conn) //读取客户端消息if err != nil {if err == io.EOF {fmt.Println("客户端退出,相关的服务器协程也退出...")return} else {fmt.Println(err)return}}err = serverProcessMes(conn, &mes) //处理客户端的消息if err != nil {fmt.Println(err)return}}
}
func main() {//提示信息fmt.Println("服务器在8889端口监听")listen, err := net.Listen("tcp", "0.0.0.0:8889")if err != nil {fmt.Println("服务器监听端口失败:", err)return}defer listen.Close()//一旦监听成功,就等待客户端来连接服务器for {fmt.Println("等待客户端来连接服务器......")conn, err := listen.Accept()if err != nil {fmt.Println("客户端连接服务器失败:", err)continue}//一旦连接成功,则启动一个协程和客户端保持通信go process(conn)}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1556262.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Vivado - JTAG to AXI Master (GPIO、HLS_IP、UART、IIC)

1. 简介 本文分享 JTAG to AXI Master IP Core 的使用教程。 此 IP 用于 AXI 接口向设计输入数据,或者读取数据。通过 Tcl 控制台编写命令来驱动此 IP,通过 JTAG 即可进行操作,而这个 IP 则在 AXI 端口上驱动 AXI 事务。由于这个核心没有自…

oh-crop: OpenHarmony/HarmonyOS上的简单的图片剪裁库,可用于头像剪裁等常见场景。

📚 简介 oh-crop: OpenHarmony/HarmonyOS上的简单的图片剪裁库,可用于头像剪裁等常见场景。 代码仓库:oh-crop 📚 下载安装 ohpm i xinyansoft/oh-cropOpenHarmony ohpm 环境配置等更多内容,请参考: 下载安装三方库…

六、Java 基础语法(下)

一、变量 1、变量的定义与使用 变量就是内存中的存储空间,空间中存储着经常发生改变的数据变量定义格式: 数据类型 变量名 数据值使用时根据变量名使用举例如下,上面是代码,下面是输出 2、变量的注意事项 变量名不允许重复…

系统分析师16:系统测试与维护

1 内容概要 2 软件测试类型 2.1 测试类型 动态测试【计算机运行】 白盒测试法:关注内部结构与逻辑灰盒测试法:介于两者之间黑盒测试法:关注输入输出及功能 静态测试【人工监测和计算机辅助分析】 桌前检查代码审查代码走查以上三个都是做的…

图解网络OSI模型与TCP/IP

一、OSI模型与TCP/IP 1、OSI模型 OSI/RM(Open System Interconnection,开放系统互联参考模型)是由ISO(国际标准组织)创建的一个有助于开放和理解计算机的通信模型,OSI七层参考模型作为一套规范的标准&…

端口冲突的解决方案以及SpringBoot自动检测可用端口demo

端口冲突的解决方案 端口冲突通常发生在尝试运行两个或多个应用程序或服务时,它们尝试使用同一个端口号,导致系统无法正确分配资源。 各种端口错误 你是否遇到过下面这些报错信息呢? Windows 系统报错: 系统错误 1004 套接字操作…

[C#]使用纯opencvsharp部署yolov11-onnx图像分类模型

【官方框架地址】 https://github.com/ultralytics/ultralytics.git 【算法介绍】 使用纯OpenCvSharp部署YOLOv11-ONNX图像分类模型是一项复杂的任务,但可以通过以下步骤实现: 准备环境:首先,确保开发环境已安装OpenCvSharp和必…

初始项目托管到gitee教程,开箱即用

0.本地仓库与远程仓库关联(需先在gitee创建仓库) ①打开powershell生成ssh key ssh-keygen -t ed25519 -C "Gitee SSH Key"-t key 类型-C 注释 生成成功如下,并按下三次回车 ②查看公私钥文件 ls ~/.ssh/输出: id_…

PPPoE协议个人理解+报文示例+典型配置-RFC2516

个人认为,理解报文就理解了协议。通过报文中的字段可以理解协议在交互过程中相关传递的信息,更加便于理解协议。 因此本文将在PPPoE协议报文的基础上进行介绍。 PPPoE协议发展 关于PPPoE基本原理,可参考1999年发布的《RFC2516-A Method fo…

大模型客服的未来发展趋势

在当今数字化时代,大模型客服正以惊人的速度改变着客户服务的格局。随着技术的不断进步,大模型客服的未来发展趋势充满了无限可能。随着人工智能技术的快速发展,智能客服领域正迎来一场前所未有的变革。大模型客服作为其中的重要分支&#xf…

32位机器上指针大小为什么是4字节?

(1)32位机器可寻址内存空间位4GB。为什么? 32位机器的总线宽度是32位,每一位可以是0或者1,那么32位可以表示个不同的值,也就是能寻址到个内存地址,每个内存地址对应一个内存单元(1个…

RFID学习

24.10.5学习目录 一.简介1.组成2.RFID协议3.RFID卡 一.简介 RFID被称为无线射频识别,其是一种通信技术,通过无线电讯号耦合识别特定目标并读写相关数据; RFID主要位于典型物联网架构中的感知层,其因为具有非接触式特性&#xff…

hiricacp 连接池校验机制

一、背景 项目发生告警,但是并没有影响业务,看了下日志,红框里面有循环调用了3次 ,一直以为是外部的重试在重试,但是外部确没有重试记录,就深扒了代码 二、想法 我知道hikaricp获取连接之后会校验连接的有…

k8s 之安装metrics-server

作者:程序那点事儿 日期:2024/01/29 18:25 metrics-server可帮助我们查看pod的cpu和内存占用情况 kubectl top po nginx-deploy-56696fbb5-mzsgg # 报错,需要Metrics API 下载 Metrics 解决 wget https://github.com/kubernetes-sigs/metri…

系统架构设计师⑦:企业信息化战略与实施

系统架构设计师⑦:企业信息化战略与实施 信息的概念及特点 信息的定义: ①香农:信息就是不确定性的减少。 ②维纳:信息就是信息,既不是物质,也不是能量。 信息的特点: ①客观性(真伪性):也叫事实性,不符…

【最新华为OD机试E卷-支持在线评测】简单的自动曝光(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 💻 ACM金牌🏅️团队 | 大厂实习经历 | 多年算法竞赛经历 ✨ 本系列打算持续跟新华为OD-E/D卷的多语言AC题解 🧩 大部分包含 Python / C / Javascript / Java / Cpp 多语言代码 👏 感谢大家的订阅➕ 和 喜欢�…

神经网络激活函数列表大全及keras中的激活函数定义

一、概述 在机器学习中,激活函数是神经网络中的一种函数,用于在神经网络的每个神经元中引入非线性。没有激活函数,神经网络就无法学习复杂的模式,因为线性变换的组合仍然是线性的。 在神经网络的每层中,将该层所有输…

设计模式之装饰器模式(Decorator)

一、装饰器模式介绍 装饰模式(decorator pattern) 的原始定义是:动态的给一个对象添加一些额外的职责。 就扩展功能而言,装饰器模式提供了一种比使用子类更加灵活的替代方案。 在软件设计中,装饰器模式是一种用于替代继承的技术,它…

【颜色平衡树 / E】

题目 思路 DFS暴力 60分 代码 #include <bits/stdc.h> using namespace std; const int N 5010; const int M 5010; int h[N], e[M], ne[M], idx; int c[N], f; int ans; void add(int a, int b) // 添加一条边a->b {e[idx] b, ne[idx] h[a], h[a] idx ; } …

Linux防火墙-常用命令

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们经过上小章节讲了Linux的部分进阶命令&#xff0c;我们接下来一章节来讲讲Linux防火墙。由于目前以云服务器为主&#x…