代做网站多少钱免费漫画软件
- 作者: 五速梦信息网
- 时间: 2026年03月21日 11:27
当前位置: 首页 > news >正文
代做网站多少钱,免费漫画软件,网站开发模型工具,均安网站建设目录 一、C/S详细通信流程图二、消息类型定义与json标签1. 消息类型定义2. JSON标签3.结构体示例及其 JSON 表示#xff1a;4.完整代码与使用说明 三、客户端发送消息1. 连接到服务器2. 准备发送消息3. 创建 LoginMes 并序列化4. 将序列化后的数据嵌入消息结构5. 序列化整个 M… 目录 一、C/S详细通信流程图二、消息类型定义与json标签1. 消息类型定义2. JSON标签3.结构体示例及其 JSON 表示4.完整代码与使用说明 三、客户端发送消息1. 连接到服务器2. 准备发送消息3. 创建 LoginMes 并序列化4. 将序列化后的数据嵌入消息结构5. 序列化整个 Message 结构体6. 发送消息长度7. 发送消息内容与完整代码8.细节解释与总结 四、服务端处理消息1. 创建缓冲区2. 循环读取客户端发送的数据3. 读取前 4 个字节4. 并发处理5. 总结与完整代码 五、测试与注意事项1.取消安全提示2.命令行中的ctrlc3.执行.exe与测试效果 一、C/S详细通信流程图 上一讲我们实现了最基本的登录功能其实根本没涉及网络编程这节开始才是网络编程而且复杂重要有一定难度。 C/S通信可用以下两张图表示 这节不涉及全部流程但涉及三块重要的内容类型定义与json标签客户端发送消息服务端处理消息。 二、消息类型定义与json标签 网络编程中通过消息Message结构体传递和处理不同类型的数据例如登录请求和登录响应。通常这些类型和消息结构体用于客户端与服务器之间的通信消息被序列化为 JSON 格式然后通过网络传输。在服务器端或客户端接收到消息后会对其进行反序列化以便处理不同类型的消息。 首先在根目录下建立message包即建立文件夹message在其中建立文件message.go然后定义消息结构体类型 package messageconst (LoginMesType LoginMesLoginResMesType LoginResMes )type Message struct {Type string json:type //消息类型Data string json:data //消息 }1. 消息类型定义 消息封装消息传输时包含不同类型的信息登录、登出、注册等需要通过一个统一的结构来表示这些消息。这就是 Message 结构体的用途。 消息分类通过 Message 中的 Type 字段可以区分消息的类型例如是登录消息LoginMes还是登录响应消息LoginResMes这样服务器和客户端可以根据 Type 做出不同的处理。 扩展性未来如果需要添加更多的消息类型例如注册、注销等可以很方便地在已有的结构上扩展新的类型而不需要重写消息传递的逻辑。
- JSON标签 JSON 标签用于指定在序列化将 Go 的结构体转换为 JSON 格式和反序列化将 JSON 格式的数据转换为 Go 结构体时结构体字段对应的 JSON 字段名。Go 中的字段名通常是驼峰命名而 JSON 中的字段名习惯上是小写或下划线分隔通过 json:“字段名” 来指定这个映射。 具体例子如下 Type string \json:type:在消息序列化为 JSON 时这个字段会被转换为 “type”。例如如果 Type 是 “LoginMes”JSON 结果会包含“type”: “LoginMes”。 Data string \json:data:这个字段包含实际的消息数据在 JSON 中也会被表示为 “data”。例如 data: {\userID:123,\userPwd:\password}也就是具体的消息数据会序列化为字符串。 3.结构体示例及其 JSON 表示 1.Message 结构体 type Message struct {Type string json:type // 消息类型Data string json:data // 消息数据 }JSON 格式 {type: LoginMes,data: {\userID:123,\userPwd:\password\,\userName:\John} }2.LoginMes 结构体 type LoginMes struct {UserID int json:userID // 用户IDUserPwd string json:userPwd // 用户密码UserName string json:userName // 用户名 }JSON 格式 {userID: 123,userPwd: password,userName: John }3.LoginResMes 结构体 type LoginResMes struct {Code int json:code // 状态码Error string json:error // 错误信息 }{code: 200,error: }4.完整代码与使用说明 message.go的完整代码如下 package messageconst (LoginMesType LoginMesLoginResMesType LoginResMes )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 //返回错误信息 } 定义这些类型是为了处理客户端和服务器之间的消息传递不同类型的消息可以通过 Message 结构体中的 Type 来识别。JSON 标签用于控制 Go 结构体字段与 JSON 字段的映射使得消息在序列化和反序列化时能够正确转换。 在通信时客户端发送登录请求会将 LoginMes 转换为 JSON 字符串并将其存放在 Message 结构体的 Data 字段中。服务器收到后会先根据 Message 的 Type 来判断消息类型例如 LoginMes然后再将 Data 字符串反序列化为 LoginMes 结构体并进行处理。服务器处理完登录请求后可以通过 LoginResMes 结构体将结果返回给客户端。 三、客户端发送消息 接下来我们转到client包完善login代码。 在登录操作中客户端与服务器通过TCP协议通信发送的是一个序列化后的消息。这是一个典型的网络编程操作流程具体包括连接服务器、序列化数据、发送消息等步骤。
- 连接到服务器 conn, err : net.Dial(tcp, localhost:8889) if err ! nil {fmt.Println(net.Dial err, err)return err } defer conn.Close() 这里使用 net.Dial 函数建立一个 TCP 连接目标地址是localhost:8889即本地的 8889 端口。 conn 是代表连接的对象通过这个连接对象客户端可以向服务器发送和接收数据。 defer conn.Close() 表示函数结束时自动关闭连接避免资源泄漏。
- 准备发送消息 var mes message.Message mes.Type message.LoginMesType这里创建了一个 Message 结构体变量 mes用于封装将要发送的消息。mes.Type 被设置为 message.LoginMesType这表示消息类型是登录消息LoginMes后续服务器会根据消息类型来识别消息的具体用途。
- 创建 LoginMes 并序列化 var loginMes message.LoginMes loginMes.UserID userID loginMes.UserPwd userPwd data, err : json.Marshal(loginMes) if err ! nil {fmt.Println(json.Marshal err, err)return err }loginMes 是一个 LoginMes 结构体包含用户ID和用户密码的信息。 使用 json.Marshal 将 loginMes 转换为 JSON 字符串便于传输。这是因为网络通信通常使用文本格式如 JSON来传输复杂数据结构。
- 将序列化后的数据嵌入消息结构 mes.Data string(data)这里将序列化后的 loginMes 作为 JSON 字符串赋值给 mes.Data即将登录信息封装到消息结构体 mes 中的 Data 字段。
- 序列化整个 Message 结构体 data, err json.Marshal(mes) if err ! nil {fmt.Println(json.Marshal err, err)return err }再次使用 json.Marshal 将整个 Message 结构体序列化为 JSON 字符串准备发送给服务器。这是因为 Message 结构体不仅包含数据还包含类型信息。
- 发送消息长度 var pkgLen uint32(len(data)) var buf [4]byte binary.BigEndian.PutUint32(buf[0:4], pkgLen) n, err : conn.Write(buf[:]) if n ! 4 || err ! nil {fmt.Println(conn.Write(bytes[:]) fail err, err)return err }网络通信中为了保证数据的完整性常常需要先发送消息的长度这里通过 len(data) 获取序列化后的消息的长度并通过 binary.BigEndian.PutUint32 函数将消息长度pkgLen转换为 4 个字节大端序存放在 buf 中。最后使用 conn.Write(buf[:]) 将消息长度发送给服务器。
- 发送消息内容与完整代码 接下来会通过 conn.Write(data) 把实际的消息数据发送给服务器这个操作将在下节讲。 login函数的完整代码如下 func login(userID int, userPwd string) 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 err, err)return err}//延时关闭defer conn.Close()//2.准备通过conn发送消息给服务器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 err, err)return err}//5.把data赋给mes.Data字段mes.Data string(data)//6.将mes进行序列化data, err json.Marshal(mes)if err ! nil {fmt.Println(json.Marshal err, err)return err}//7.到这个时候data就是我们要发送的消息//7.1 先把data的长度发送给服务器// 先获取到data的长度-转成一个表示长度的byte切片var pkgLen uint32(len(data))var buf [4]bytebinary.BigEndian.PutUint32(buf[0:4], pkgLen)//发送长度n, err : conn.Write(buf[:4])if n ! 4 || err ! nil {fmt.Println(conn.Write(bytes[:]) fail err, err)return err}fmt.Printf(客户端发送消息的长度%d\n内容%s\n, len(data), string(data))return nil }8.细节解释与总结 1为什么使用大端序 在网络传输中为了保证跨平台数据的一致性通常会采用大端序Big Endian来传输数据。因为大端序的字节排列方式与人类阅读数字的顺序一致。高位字节在前低位字节在后和我们书写数值的方式相同。 举个例子假设 pkgLen 123456 (十六进制为 0x0001E240)则 binary.BigEndian.PutUint32(buf[0:4], pkgLen) 将执行以下操作 buf[0] 0x00 buf[1] 0x01 buf[2] 0xE2 buf[3] 0x40 最终 buf[0:4] 就包含了 pkgLen 的大端序表示。 2为什么需要发送长度 在网络通信中消息的长度是动态的接收方通常不知道需要读取多少数据。如果直接发送数据接收方可能无法正确判断消息的结束。 因此发送方先发送一个固定长度的消息如4个字节的消息长度让接收方根据这个长度来接收完整的消息。 3客户端发消息其实就为四步 1.连接服务器 2.初始化并序列化消息变种 3.用消息变种初始化并序列化消息 4.发送消息的长度与内容 四、服务端处理消息 在server包下创建main.go自定义process函数其核心内容如下
- 创建缓冲区 buf : make([]byte, 1024*4) //准备缓冲区以读取数据这里使用 make 函数创建了一个大小为 4KB1024 * 4 字节的缓冲区 buf用于存放从客户端接收到的数据。
- 循环读取客户端发送的数据 for {fmt.Println(读取客户端发送的数据)//… }使用 for 循环持续监听并读取来自客户端的数据直到出现错误或者连接断开。循环不断地执行读取操作保证服务器可以持续处理客户端发送的消息。
- 读取前 4 个字节 n, err : conn.Read(buf[:4]) if n ! 4 || err ! nil {fmt.Println(conn.Read err, err)return }conn.Read(buf[:4])从连接 conn 中读取最多 4 个字节读取的数据存储在 buf 数组的前 4 个字节位置。 返回值 n表示读取了多少个字节。理想情况下n 应该为 4表示完整读取了 4 个字节的数据。 接下来要判断连接是否正常如果读取的字节数不是 4即读取不完整或发生了错误则输出错误信息并退出 process 函数终止该连接的处理。
- 并发处理 在第二节我讲了客户端与服务端的基本通信操作在服务端每个客户端连接都通过新的协程来处理这使得服务器能够同时与多个客户端进行通信而不会因为一个客户端的阻塞操作如读取数据而影响其他客户端。其中listen.Accept()是关键操作它的作用是阻塞主协程并等待客户端连接连接成功后返回一个用于与客户端通信的conn对象。
- 总结与完整代码
server包下的main.go要实现一个简单的并发 TCP 服务器即 监听 TCP 连接并发处理错误处理以及资源释放即通过 defer 机制服务器会在程序结束时正确释放资源关闭监听器。完整代码如下
package mainimport (fmtnet
)// 处理和客户端的通信
func process(conn net.Conn) {//这里需要延时关闭conndefer conn.Close()buf : make([]byte, 1024*4) //准备缓冲区以读取数据//循环读取客户端发送的信息for {fmt.Println(读取客户端发送的数据)n, err : conn.Read(buf[:4])if n ! 4 || err ! nil {fmt.Println(conn.Read err, err)return}fmt.Println(读到的buf, buf[:4])}
}
func main() {//提示信息fmt.Println(服务器在8889端口监听)listen, err : net.Listen(tcp, 0.0.0.0:8889)if err ! nil {fmt.Println(net.Listen err, err)return}defer listen.Close()//一旦监听成功就等待客户端来连接服务器for {fmt.Println(等待客户端来连接服务器……)conn, err : listen.Accept()if err ! nil {fmt.Println(listen.Accept err, err)}//一旦连接成功则启动一个协程和客户端保持通信go process(conn)}
}
五、测试与注意事项
1.取消安全提示
如果是windows操作系统在执行server包的程序时可能会弹出“是否允许公共网络访问”这样的提示最直接的办法就是关闭防火墙当然如果你网络编程的时间较长并且一直在上网这是有风险的。还有种就是将server包下的服务器程序比如server.exe加入信任列表。当然前提是编译server包即在项目根目录下执行如下命令
go build ./server然后在win底部菜单栏中win10/11适用输入“允许应用通过”此时会弹出下图 点击进入设置界面再按下图操作 然后浏览并添加即可。
2.命令行中的ctrlc
这里的ctrlc可不是复制而是用于命令行中结束程序一般的命令行比如windows cmd一旦开启server.exe只能通过右上角的关闭按钮结束但如果用powershell执行程序则用ctrlc就能结束这样就能保留命令行记录与操作按上方向键能查看旧命令。注意如果你用的IDE是vscode则内置终端默认就是powershell而且可以启动多个终端并分屏查看。至于快捷键调出的外部命令行是无法使用ctrlc的。
3.执行.exe与测试效果
打开两个powershell命令行在当前根目录下执行两个编译好的程序client.exe和server.exe
./server.exe./client.exe效果如图
OK以上就是登录模块的核心功能了这也是网络编程的基础与重点可以说不掌握本节内容是无法入门的。本节内容多不简单读者需要多次阅读和编程才能掌握。
- 上一篇: 代做网页制作网站wordpress系统搭建
- 下一篇: 代做网站多少钱什么兼职网站可以做视频剪辑
相关文章
-
代做网页制作网站wordpress系统搭建
代做网页制作网站wordpress系统搭建
- 技术栈
- 2026年03月21日
-
代做论文的网站有哪些好的深圳装修网站建设
代做论文的网站有哪些好的深圳装修网站建设
- 技术栈
- 2026年03月21日
-
代做课题网站h5海报是什么意思
代做课题网站h5海报是什么意思
- 技术栈
- 2026年03月21日
-
代做网站多少钱什么兼职网站可以做视频剪辑
代做网站多少钱什么兼职网站可以做视频剪辑
- 技术栈
- 2026年03月21日
-
代做网站公司哪家好营销型网站哪家做的好
代做网站公司哪家好营销型网站哪家做的好
- 技术栈
- 2026年03月21日
-
代做网站关键词排名vue做的个人网站
代做网站关键词排名vue做的个人网站
- 技术栈
- 2026年03月21日






