day3| 从socket部分继续学习

package mainimport ("fmt""log""net/http""github.com/gorilla/websocket"
)var UP = websocket.Upgrader{/*握手时间缓冲区(包括写和读)缓冲池指定用于生成HTTP错误响应的函数对过来的请求进行校验指定服务器是否应尝试根据进行协商消息压缩*/ReadBufferSize:  1024,WriteBufferSize: 1024,
}var conns []*websocket.Connfunc handler(w http.ResponseWriter, r *http.Request) {conn, err := UP.Upgrade(w, r, nil)if err != nil {log.Println(err)return}conns = append(conns, conn)for {m, p, e := conn.ReadMessage() //读取消息if e != nil {fmt.Println(err)break}for i := range conns {conns[i].WriteMessage(websocket.TextMessage, []byte(string(p)))//变成渣男了,可以对所有给他发消息的人进行说话}fmt.Println(m, string(p))}defer conn.Close()log.Println("服务关闭")
}
func main() {http.HandleFunc("/", handler)http.ListenAndServe(":8888", nil)}
package mainimport ("bufio""fmt""github.com/gorilla/websocket""os"
)func main() {dl := websocket.Dialer{} //这是websocket提供的的结构体/*一切提供的东西都和业务挂钩,和学习无关*/conn, _, err := dl.Dial("ws://127.0.0.1:8888", nil)if err != nil {fmt.Println(err)return}go send(conn)for {m, p, e := conn.ReadMessage()if e != nil {break}//只要连接还在,不断的读fmt.Println(m, string(p))}
}func send(conn *websocket.Conn) {for {reader := bufio.NewReader(os.Stdin)l, _, _ := reader.ReadLine()conn.WriteMessage(websocket.TextMessage, l)}
}

首先需要了解下列知识:

WebSocket 是一种在单个 TCP 连接上提供全双工通信的网络协议。它可以让客户端和服务器之间进行双向通信,而无需通过 HTTP 请求和响应。在理解 WebSocket 的底层代码知识时,以下是您可能需要了解的一些重要概念:

  1. 握手(Handshake)
  • WebSocket 通信始于一个 HTTP 握手过程,客户端发起 WebSocket 握手请求,服务器接受并响应这个请求,然后建立起 WebSocket 连接。

  • 握手过程通常发生在 HTTP/HTTPS 的特定端点上,例如 "/ws" 或 "/websocket"。

  1. 帧(Frame)
  • WebSocket 数据通过帧进行传输,每个帧代表了一个消息的一部分。

  • 帧可以是文本、二进制数据或控制帧。控制帧用于连接管理,例如关闭连接。

  1. 数据帧格式
  • 数据帧通常由几个字节的控制头部和数据部分组成。

  • 控制头部包括一些标志位和指示数据类型的信息,如数据是否被分片、数据类型(文本或二进制)、是否是最后一个片段等。

  1. 状态码(Status Codes)
  • WebSocket 握手过程和连接管理中使用了一系列状态码来表示不同的状态和结果。

  • 例如,101 表示握手成功,而 1006 表示连接异常关闭。

  1. 心跳(Heartbeat)
  • 为了保持连接活跃,WebSocket 可以周期性地发送心跳帧。

  • 心跳帧通常是空的或包含特定的数据,用于告知对端连接依然存在。

  1. 拓展(Extensions)
  • WebSocket 支持通过拓展机制增加协议的功能。

  • 拓展可以用于压缩数据、加密通信等目的。

  1. 子协议(Subprotocols)
  • WebSocket 握手阶段可以指定一个或多个子协议,以便客户端和服务器之间选择适当的通信协议。
  1. 安全性
  • WebSocket 连接的安全性可以通过使用 TLS/SSL 加密来保障。

  • 这通常通过在标准的 HTTP(S) 端口上启用 WebSocket,或者在自定义端口上使用 wss:// URL 来实现

gin包

r := gin.Default()/*GET 查  ->放在地址栏里面uri传参POST 增  ->参数在form /body /uriDELETE 删  -> uri同样也可以用bodyPUT 改   -> 参数在 form/body/uriRestful 就是这四款uri的格式:"/path/:id" 可以取得id只存在面试*/r.GET("/path/:id", func(c *gin.Context) {id := c.Param("id")//user是放在地址栏后面的,我们称为Query传参user := c.Query("user")//如果说想要有一个默认值user := c.DefaultQuery("user", "qimiao")、//就是我输入uri的时候是没有user这个值的,但是反馈到服务器是需要有的pwd := c.Query("pwd")c.JSONP(200, gin.H{"id":   id,"user": user,"pwd":  pwd,})})r.POST("/path", func(c *gin.Context) {/*form表单*/user := c.DefaultPostForm("user", "xzc")pwd := c.PostForm("pwd")c.JSONP(200, gin.H{"user": user,"pwd":  pwd,})})r.DELETE("/path/:id", func(c *gin.Context) {id := c.Param("id")//DELETE也可以解析表单c.JSONP(200, gin.H{"id":  id,})})r.PUT("/path", func(c *gin.Context) {/*form表单*/user := c.DefaultPostForm("user", "xzc")pwd := c.PostForm("pwd")c.JSONP(200, gin.H{"user": user,"pwd":  pwd,})})

接着来到第二课,接触了Bind,这个是啥嘞

有时候听他说话都听不懂,我心想第二遍肯定会好点

type PostParm struct {Name string `json:"name"`Age  int    `json:"age"`Sex  bool   `json:"sex"`
}
r := gin.Default()r.POST("/testBind", func(c *gin.Context) {var p PostParmerr := c.ShouldBind(&p)if err != nil {c.JSON(200, gin.H{"msg":  "wrong","data": gin.H{},})} else {c.JSON(200, gin.H{"msg":  "success","data": p,})}})

之后又增加了Query and uri的绑定形式

type PostParm struct {Name string `json:"name" uri:"name" form:"name"`Age  int    `json:"age" uri:"age" form:"age"`Sex  bool   `json:"sex" uri:"sex" form:"sex"`
}func main() {r := gin.Default()r.POST("/testBind", func(c *gin.Context) {var p PostParmerr := c.ShouldBindQuery(&p) //这里换上之后 上面的结构体会增加tag//err := c.ShouldBindURI(&p)if err != nil {c.JSON(200, gin.H{"msg":  "wrong","data": gin.H{},})} else {c.JSON(200, gin.H{"msg":  "success","data": p,})}})

还有一个shouldBind这里可以大致看一下

// If `GET`, only `Form` binding engine (`query`) used.// 如果是Get,那么接收不到请求中的Post的数据??// 如果是Post, 首先判断 `content-type` 的类型 `JSON` or `XML`, 然后使用对应的绑定器获取数据.// See more at https://github.com/gin-gonic/gin/blob/master/binding/binding.go#L48if c.ShouldBind(&person) == nil {log.Println(person.Name)log.Println(person.Address)log.Println(person.Birthday)}

如果是GET,那么这个方法就只会拿到query数据

如果是POST,会判断content-type的格式

//之后我们研究这个binding,这其实是一个表单验证的功能
type PostParm struct {Name string `json:"name" binding:"required"`Age  int    `json:"age" binding:"required"`Sex  bool   `json:"sex" biding:"required"`
}r.POST("/testBind", func(c *gin.Context) {var p PostParmerr := c.ShouldBindJSON(&p) //这里换上之后 上面的结构体会增加tagif err != nil {fmt.Println(err.Error())c.JSON(200, gin.H{"msg":  "wrong","data": gin.H{},})} else {c.JSON(200, gin.H{"msg":  "success","data": p,})}})

然后我们做了一个实验,如果我们只传入name这个参数,将会返回什么呢

image.png

image.png

这个是返回的一个错误,说我们age的必填项没有填

然后我们继续加限制

type PostParm struct {Name string `json:"name" `Age  int    `json:"age" binding:"required,mustBig"`Sex  bool   `json:"sex" `
}
//然后接下来的什么,这个mustBig又自己写了一个func mustBig(f1 validator.FieldLevel) bool {if f1.Field().Interface().(int) <= 18 {return false}return true
}//验证规则
/*
内部通过反射的形式判断年龄的大小是否符合标准*/
//main里面在 接收前也要编写一个if v, ok := binding.Validator.Engine().(*validator.Validate); ok {v.RegisterValidation("mustBig", mustBig)}

image.png

这个是报错的信息,说明它违反了mustBig的tag

r.POST("/testBind", func(c *gin.Context) {if v, ok := binding.Validator.Engine().(*validator.Validate); ok {v.RegisterValidation("mustBig", mustBig)//绑定一个注册规则}var p PostParmerr := c.ShouldBindJSON(&p) //这里换上之后 上面的结构体会增加tagif err != nil {fmt.Println(err.Error())c.JSON(200, gin.H{"msg":  "wrong","data": gin.H{},})} else {c.JSON(200, gin.H{"msg":  "success","data": p,})}})r.Run(":8080")

一般情况要使用ShouldBind,因为MustBind返回的code不好控制

ShouldBind有一个自定义验证

gin对于文件的接受和返回

前端给后端传文件

首先设置Header

image.png

然后再发送文件

联想截图_20240331215611.png

r.POST("/testUpload", func(c *gin.Context) {file, _ := c.FormFile("file")c.SaveUploadedFile(file, "./"+file.Filename) //接受一个文件的格式还有路径(保存位置)/*会返回一个文件流和err*/c.JSON(200, gin.H{"msg": file,})})
r := gin.Default()r.POST("/testUpload", func(c *gin.Context) {file, _ := c.FormFile("file")//将文件和postform都传给后台//接收文件in, _ := file.Open()defer in.Close()out, _ := os.Create("./" + file.Filename)//接受一个文件路径还有一个名字,用来搞清楚保存在哪里defer out.Close()io.Copy(out, in)//给前端返回文件c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment;filename=%s", file.Filename))c.File("./" + file.Filename)})

第二遍看需要自己手动写了

file, _ := c.FormFile("file")in, _ := file.Open()//打开文件并知晓其内容defer in.Close()out, _ := os.Create("./"+file.Filename)//在给定的路径下创建一个文件defer out.Close()io.Copy(out,in)//将一开始复制的文件中的内容复制到刚创建的文件

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RUST Rover 条件编译 异常处理

按官方处理发现异常 会报异常 error: failed to parse manifest at C:\Users\topma\RustroverProjects\untitled2\Cargo.toml 修改模式如下才能正常编译 网上说明 这样处理 [features] print-a [] print-b [] full ["print-a","print-b"]

Mybatis——一对多关联映射

一对多关联映射 一对多关联映射有两种方式&#xff0c;都用到了collection元素 以购物网站中用户和订单之间的一对多关系为例 collection集合的嵌套结果映射 创建两个实体类和映射接口 package org.example.demo;import lombok.Data;import java.util.List;Data public cla…

LabVIEW专栏二、调用子VI

该节目标是创建带子vi&#xff0c;修改vi属性&#xff0c;测试可重入和不可重入的区别 一 、设置子VI 把VI封装成为子VI&#xff0c;可以帮助模块化程序&#xff0c;简化代码结构。 任何VI本身都可以成为别的VI的子VI。 1.1、设置输入输出端子 1、在前面板空白处&#xff0…

Matlab|基于关键场景辨别算法的两阶段鲁棒微网优化调度

目录 主要内容 部分代码 结果一览 下载链接 主要内容 该模型主要求解的是微网两阶段鲁棒优化调度问题&#xff0c;与目前大部分用CCG算法不同&#xff0c;模型创新性的采用关键场景辨别法&#xff0c;通过少量的迭代辨别出最恶劣的场景&#xff0c;针对光伏出力的…

obs直播推流 + ffmpeg参数

OBS 启动参数设为 --startstreaming &#xff0c; 可以让它启动后自动开始直播 对应ffmpeg参数&#xff1a; echo off :loop ffmpeg -re -i a.mp4 -r 24 -c:v libx264 -preset ultrafast -profile:v baseline -g 24 -keyint_min 24 -x264-params nal-hrdcbr -b:v 2500k -minr…

洛谷P1000超级玛丽游戏题解[Python, Rust, Go]

题目 打印超级玛丽字符图像 小技巧 直接复制题目的超级玛丽符号首行会有空格问题&#xff0c;一直AC不过&#xff0c;一行一行地复制就OK了&#x1f44c;。 Rust 题解 fn main() {println!(" ********************####....#.#..###.....##....###...…

企业周年庆3d云展厅促进了客企间交流与互动

在数字化浪潮席卷而来的今天&#xff0c;传统的展示方式已难以满足现代人对信息获取与体验的高标准需求。为此&#xff0c;一种革命性的展示方式——线上3D虚拟展厅应运而生&#xff0c;以其独特的魅力逐渐引领展示方式的革新。 线上3D虚拟展厅开发&#xff0c;不仅为参与者带来…

JVM垃圾收集——相关概念

本贴讲解的内容包括System.gc()、内存溢出、内存泄漏、STW机制以及垃圾收集的串行、并行、并发三种情况&#xff0c;还有强引用、软引用、弱引用、虚引用四种引用。 1、System.gc()的理解 在默认情况下&#xff0c;通过System.gc()或者Runtime.getRuntime().gc()的调用&#…

提升常州小程序软件开发的搜索排名:关键步骤解析

在移动互联网的浪潮中&#xff0c;小程序作为连接用户与服务的桥梁&#xff0c;其重要性日益凸显。对于常州的小程序软件开发企业来说&#xff0c;如何让自己的产品在浩如烟海的互联网信息中脱颖而出&#xff0c;提升搜索排名&#xff0c;成为了亟待解决的问题。本文将为您解析…

HarmonyOS 应用开发之自定义组件冻结功能

自定义组件处于非激活状态时&#xff0c;状态变量将不响应更新&#xff0c;即Watch不会调用&#xff0c;状态变量关联的节点不会刷新。通过freezeWhenInactive属性来决定是否使用冻结功能&#xff0c;不传参数时默认不使用。支持的场景有&#xff1a;页面路由&#xff0c;TabCo…

什么是智慧公厕?智慧旅游下的智慧公厕功能和特点

智慧旅游下的智慧公厕功能和特点&#xff1f;智慧旅游是景区、公园、游乐场、文化场馆等领域的一种信息化解决方案&#xff0c;智慧公厕是智慧旅游极为重要的一部分&#xff0c;能大大提升游客满意度。智慧公厕采用物联网、互联网、大数据、云计算等技术&#xff0c;实现旅游景…

使用Excel连接Azure DevOps自动退出的问题

Azure DevOps Server (原名TFS)是微软公司的软件开发管理平台&#xff0c;也是著名的软件开发过程管理工具&#xff1b;系统中记录了软件开发过程中的需求、问题、缺陷和迭代计划等各种软件开发工作项数据。 对于工作项数据的批量操作(例如新增和编辑)&#xff0c;Excel是一个非…

zabbix图表时间与服务器时间不一致问题

部署完zabbix后&#xff0c;有时候会发现zabbix服务器的时间明明是对的&#xff0c;但是图标的时间不对&#xff0c;通过以下的配置可以快速解决。 登录zabbix-nginx容器 docker exec -u root -it docker-compose-zabbix-zabbix-web-nginx-mysql-1 bash修改php配置文件 vi /e…

SpringData ElasticSearch - 简化开发,完美适配 Spring 生态

目录 一、SpringData ElasticSearch 1.1、环境配置 1.2、创建实体类 1.3、ElasticsearchRestTemplate 的使用 1.3.1、创建索引 设置映射 1.3.2、简单的增删改查 1.3.3、搜索 1.4、ElasticsearchRepository 1.4.1、使用方式 1.4.2、简单的增删改查 1.4.3、分页排序查…

Linux系统下安装jdk与tomcat【linux】

一、yum介绍 linux下的jdk安装以及环境配置&#xff0c;有两种常用方法&#xff1a; 1.使用yum一键安装。 2.手动安装&#xff0c;在Oracle官网下载好需要的jdk版本&#xff0c;上传解压并配置环境。 这里介绍第一种方法&#xff0c;在此之前简单了解下yum。 yum 介绍 yum&…

57 npm run build 和 npm run serve 的差异

前言 npm run serve 和 npm run build 的差异 这里主要是从 vue-cli 的流程 来看一下 我们经常用到的这两个命令, 他到传递给 webpack 打包的时候, 的一个具体的差异, 大致是配置了那些东西? 经过了那些流程 ? vue-cli 的 vue-plugin 的加载 内置的 plugin 列表如下, 依次…

【Go】二十、反射

文章目录 1、反射2、对基本数据类型反射3、对结构体进行反射4、获取变量的类别5、通过反射修改基本类型变量的值6、通过反射操作结构体的属性和方法 1、反射 //核心包 import ("reflect")通过反射&#xff1a; 可以在运行时动态获取变量的类型、获取结构体的信息&a…

【二叉树】Leetcode 124. 二叉树中的最大路径和【困难】

二叉树中的最大路径和 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点&#xff0c;且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的根…

【QT+QGIS跨平台编译】056:【pdal_json_schema+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

点击查看专栏目录 文章目录 一、pdal_json_schema介绍二、pdal下载三、文件分析四、pro文件五、编译实践一、pdal_json_schema介绍 pdal_json_schema 是与 PDAL(Point Data Abstraction Library)相关的 JSON 模式文件。PDAL 是一个用于处理和分析点云数据的开源库。JSON 模式…

Flutter混淆方案对应用性能的影响分析与优化

在移动应用开发中&#xff0c;保护应用代码安全至关重要。Flutter 提供了简单易用的混淆工具&#xff0c;帮助开发者在构建 release 版本应用时有效保护代码。本文将介绍如何在 Flutter 应用中使用混淆&#xff0c;并提供了相关的操作步骤和注意事项。 &#x1f4dd; 摘要 本…