Go红队开发—web网络编程
文章目录
- web网络编程
- Req
- 快速请求
- 调试
- DevMode
- DebugLog
- TraceInfo瓶颈分析
- 控制请求与响应
- 控制请求的字段内容
- 控制调试打印的内容
- 分开dump请求与响应部分
- 请求体设置
- 作用范围级别
- 设置参数查询
- URL 路径参数
- 表单请求设置
- 请求头设置
- 判断响应状态码
- 解析数据
- SetSuccessResult
- gjson
- 响应数据解析练习
- Cookie
- 默认行为
- 禁⽤Cookie
- 存储Cookie
- 证书校验
- 无视风险
- 配置证书
- Auth身份认证
- 文件上传下载
- 上传文件
- 下载文件
- 多线程下载练习
web网络编程
tips:这一章的铺垫比较重要,这章过后就是一些安全工具如何编写以及一些poc、exp的工具编写。
Req
简单的请求
- 客户端创建
- 请求设置

func reqHttp() {client := req.C() //客户端创建res, err := client.R(). //请求设置,这个点的意思链式调用,后续在控制请求中会讲Get("https://httpbin.org/uuid")if err != nil {log.Println("请求失败:", err)}fmt.Println(res)}
快速请求
- MustGet
测试使用可以,正式开发不建议使用,可控性差
// 快速使用,一般用在test的时候func testHttp() {resp := req.MustGet("https://httpbin.org/uuid") //这里就是发起了一次请求fmt.Println(resp.String()) //第一种打印*req.Response类型的响应体fmt.Println(string(resp.Bytes())) //第二种打印*req.Response类型的响应体}
调试
DevMode
DevMode是直接开启全局调试,自动打印出来
// 调试模式func devModeReq() {//使用req进行请求,所以req的调试模式也是在req启动req.DevMode() //开启调试模式,就会打印出来请求的过程以及响应内容req.SetCommonBasicAuth("username", "password"). //设置用户名和密码SetTimeout(5 * time.Second). //设置超时时间SetUserAgent("my-ua")resp := req.MustGet("https://httpbin.org/uuid")//没有开启调试模式但是想打印的话就正常打印fmt.Println(resp.String()) //第一种打印*req.Response类型的响应体fmt.Println(string(resp.Bytes())) //第二种打印*req.Response类型的响应体}
DebugLog
DebugLog 是跟踪请求的过程

他可以看到你整个请求的过程,重定向的信息等等
// 查看请求的过程发生了什么func deLog() {client := req.C().EnableDebugLog() //开启DebugLogclient.R().Get("http://baidu.com/s?wd=req")}
TraceInfo瓶颈分析
trace跟踪信息

func traceReq() {// Enable trace at request levelclient := req.C()resp, err := client.R().EnableTrace(). //开启瓶颈分析Get("https://api.github.com/users/imroc")if err != nil {log.Fatal(err)}trace := resp.TraceInfo() //trace跟踪信息fmt.Println(trace.Blame()) //分析总结(请求减慢的原因归咎)fmt.Println(trace) // 打印内容}
控制请求与响应
控制请求的字段内容
这里做一个了解,后面会详细说一下作用范围,这里就过一遍即可,知道哪些字段可控(其实都可控)
func controlReq() {client := req.C().SetUserAgent("my-ua"). //设置ua头,在client中设置,在下面的R()中设置不了//EnableDumpAllToFile("log.txt") //将请求的信息写到该文件中//捕获请求和响应,// 想要看的更加详细就可以开启dump所有内容,// 就能够看到我们是不是真的改变了请求内容EnableDumpAll()parms := map[string]string{"a": "123","b": "hello",}resp, err := client.R(). //拿到请求体SetPathParam("usernamae", "imroc"). //设置请求路径,用username作为占位符SetPathParam("xxx", "test"). //再次设置,用xxx作为占位符SetQueryParam("a", "12"). //设置请求参数,a=12SetQueryParams(parms). //用map来作为请求参数,用于多个参数的时候SetHeader("mycookie", "test"). //设置请求头SetHeader("mysession", "test2"). //设置请求头SetBody("body=world"). //设置请求体Get("https://httpbin.org/uuid")//以上设置暂时在初期阶段够用了。if err != nil {log.Println("请求出错:", err)}fmt.Println(resp)}
控制调试打印的内容
- SetCommonDumpOptions:控制输出的内容
- EnableDumpAllToFile:dump到文件中
输出的log2.txt文件内容如下

// 控制调试打印的内容// 全局应用func controlDevOptions() {client := req.C()opt := &req.DumpOptions{Output: os.Stdout, //标准输出RequestHeader: false, //不输出请求头RequestBody: false, //不输出请求体ResponseHeader: true, //输出响应头ResponseBody: true, //输出响应体Async: false, //不进行异步输出}client.SetCommonDumpOptions(opt).EnableDumpAllToFile("log2.txt")client.R().Get("https://httpbin.org/uuid")}
分开dump请求与响应部分
var bufReq, bufResp bytes.Buffer:需要用变量来接收请求与响应不同部分- SetDumpOptions:控制dump导出部分
// 分别打印请求与响应部分// 在R中控制调试打印的内容,只作用与本次R请求,与上面的client直接全局设置的不同func controlReqRespOutPut() {client := req.C()var bufReq, bufResp bytes.Bufferclient.R().// 不开启的话就会导致无法转储出去单独打印请求体响应体EnableDump(). //EnableDump启用转储,包括请求和响应的所有内容。SetDumpOptions(&req.DumpOptions{RequestOutput: &bufReq, //将请求体输出到这里ResponseOutput: &bufResp, //将响应体输出到这里RequestHeader: true,RequestBody: true,ResponseHeader: true,ResponseBody: true,}).SetBody("body=hello+world!").Get("https://httpbin.org/uuid")fmt.Println("请求体")fmt.Println(bufReq.String())fmt.Println("响应体")fmt.Println(bufResp.String())}
请求体设置
SetBody 可以接受任意类型
PS: EnableDumpAllWithoutResponse因为开启了调试模式,所以会打印很多东西,但是可以忽略响应打印出来结果,所以这函数就是忽略响应结果,只看请求。

在编写一些poc/exp的时候可能需要在body部分,需要加入一些结构体或者map数据,他会根据你设置的content-type来判断解析成json还是xml格式,如果都不设置的话他会默认将这些类型解析为json数据body。

添加上content-type类型后就自动转了,比较方便(后面还有更方便的)

- SetBodyXXX
不用设置content-type也能直接转想要的格式了

以下是代码:
// 设置请求体中的一些骚姿势func setbodyHttp() {type test struct {Name stringAge int}t := test{Name: "zhangsan",Age: 123,}client := req.C().DevMode().EnableDumpAllWithoutResponse()client.R().SetBody(t).SetContentType("application/xml").Get("https://httpbin.org/uuid")client2 := req.C().DevMode().EnableDumpAllWithoutResponse()client2.R().SetBodyXmlMarshal(t).Get("https://httpbin.org/uuid")}
作用范围级别
在设置请求参数的时候,有分两种作用范围设置,一种全局(客户端级别),另一种就是只作用与这一个client的对象(请求级别)。
以下就尽量快速过为妙,上面学的时候已经有很多函数都用过了,没必要花太多时间,知道即可,下面作为一个知识字典,以后方便查阅。
请记住:
用req.C().R()来设置的请求级别用req.C()来设置的是全局级别(也即客户端级别client)
设置参数查询
请求级别:
- SetQueryParam:
SetQueryParam("test", "123")即 httpxxx?test=123
设置多个的时候仅仅对最后一个设置的生效 - SetQueryParams:SetQueryParams接收map类型设置多个变量,由于map的键唯一,所以多个同名的话也只会作用一个。
- SetQueryString:直接给查询参数即可,
SetQueryString("test1=123&test2=456")
这个不会产生什么重复覆盖问题,字符串给啥他就拼接到你url中去 - AddQueryParam:
AddQueryParam("key", "value1")如果该参数已存在,它不会覆盖原有的值,这个一般用在你临时需要添加什么查询参数的时候可以用,而且不会覆盖原有的同名键值
全局级别:
- SetCommonQueryParam
- SetCommonQueryParams
- SetCommonQueryString
- AddCommonQueryParam
URL 路径参数
请求级别:
- SetPathParam:
SetPathParam("username", "zhangsan") - SetPathParams:接收map类型
全局级别:
- SetCommonPathParam
- SetCommonPathParams
表单请求设置
请求级别:
- SetFormData:接收map类型,但是同一个键只能有一个
- SetFormDataFromValues::
代码如下所示,但是注意的是url.Values是net/url包,所以要注意这个url不是我定义的,拿来就用即可。
client3 := req.C().DevMode().EnableDumpAllWithoutResponse()v := url.Values{"p": []string{"hello", "world", "!"},
}
client3.R().SetFormDataFromValues(v).Post("https://httpbin.org/post")

- multipart ⽅式提交表单:
EnableForceMultipart
client3 := req.C().DevMode().EnableDumpAllWithoutResponse()
v := url.Values{"p": []string{"hello", "world", "!"},
}
client3.R().EnableForceMultipart().SetFormDataFromValues(v).Post("https://httpbin.org/post")

全局级别:
- SetCommonFormData
- SetCommonFormDataFromValues
请求头设置
请求级别:
- SetHeader:自动将你传进的header键的首字母大写
- SetHeaders:接收map类型,自动将你传进的header键的首字母大写
- SetHeaderNonCanonical:你给什么样就输出什么样,不会自动给你首字母大写
- SetHeadersNonCanonical:你给什么样就输出什么样,不会自动给你首字母大写
- SetHeaderOrder:控制header的顺序,因为有的服务端可能会对header的顺序判断是否允许请求,设置了SetHeaderOrder,他就会按照你给定的顺序进行排序请求过去。
request.SetHeaderOrder( "cookie", "ssession", "test","ua",
)
全局级别
- SetCommonHeaderNonCanonical
- SetCommonHeadersNonCanonical
判断响应状态码
没啥好说的,都到这了这些应该对于各位师傅来说都是一眼就学会的基操了。
- resp.IsSuccessState
- resp.IsErrorState
- resp.StatusCode
// 判断响应状态码func judgeStatusCode() {client := req.C()resp, err := client.R().Get("http://www.baidu.com")if err != nil {log.Println("请求失败:", err)}if resp.IsSuccessState() {fmt.Println("ok")}if resp.IsErrorState() {fmt.Println("error")}//可以通过响应对应的代码判断if resp.StatusCode != http.StatusOK { //http有一个const变量,里面有很多对应的响应码,自行查看即可(文件:http\status.go)fmt.Println("error")}//打印响应体fmt.Println(resp.Bytes()) //bytes打印fmt.Println(resp.String()) //string打印}
解析数据
SetSuccessResult
-
SetSuccessResult:SetSuccessResult会⾃动解析你给的结构体或map
-
SetErrorResult
这里一同把SetErrorResult也讲了,可以自定义错误解析到你自己定义的错误中去,没啥好说感觉也时,定义好了就直接给到SetErrorResult即可(详细见代码处)
运行结果如下图所示:

// 接收响应回来的json数据type user struct {Login string `json:login`Id int `json:id`Name string `json:name`}// 接收错误响应type errorResp struct {Mess string `json:message`}// 解析响应的json数据// SetSuccessResult⾃动解析结构体或mapfunc getHttpJson() {client := req.C()var respUser uservar respError errorRespres, err := client.R().SetSuccessResult(&respUser). //接收响应回来的json数据,同时也可以解析mapSetErrorResult(&respError). //若请求错误将错误信息存储到该结构体中Get("https://api.github.com/users/whoisdhan")if err != nil {log.Println("代码请求出错:", err)return}if res.IsSuccessState() {fmt.Println("请求成功")fmt.Println(respUser.Login)fmt.Println(respUser.Id)fmt.Println(respUser.Name)} else if res.IsErrorState() {fmt.Println("网络请求出错:", respError.Mess)} else {fmt.Println("未知错误:", res.StatusCode)}}
gjson
字段名、.:表示读取该字段,字段名.0表示读取该键名下的数据的第一个字段,字段名.1读取第二个*、?:gjson支持通配符:像在linux命令行中使用的通配符那样用就行,a*a收尾为a的都匹配#:表示该字段所有元素。- 在结尾:
字段名1.字段名2.#表示返回字段名2的数组长度 - 在中间,即
#后面还有内容:字段名1.#.字段名2表示返回字段名2所有元素 - 原因:这也是为啥我叫他
#的意思是表示该字段所有元素,在结尾就是返回长度,不在就是返回整个数组列表
- 在结尾:
gjson解析json数据可提取指定字段,不用定义结构体
gjson非常适合提取几个字段出来之类的,方便的一笔。

// 由于我们的http请求回来的数据能方便的转为string所以也能用gjson// 模拟数据const httpjson = `{"name":{"first":"Tom", "last": "Anderson"},"age": 37,"children": ["Sara", "Alex", "Jack"],"fav.movie": "Dear Hunter","friends": [{"first": "Dale", "last":"Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},{"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},{"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}]}`func gjsonHttp() {//先简单用正常的httpjson数据尝试一下client := req.C()resp, _ := client.R().Get("https://api.github.com/users/whoisdhan")login := gjson.Get(resp.String(), "login")id := gjson.Get(resp.String(), "id")name := gjson.Get(resp.String(), "name")fmt.Println(login, id, name)//用httpjson测试数据fmt.Println(gjson.Get(httpjson, "name.first"))fmt.Println(gjson.Get(httpjson, "friends.#.first"))fmt.Println(gjson.Get(httpjson, "friends.#.nets"))fmt.Println(gjson.Get(httpjson, "fav\\.movie")) //字段存在符号的话用\\转义}
响应数据解析练习
这里的解析可能有点主观了,可以按照自己的想法,尽量不要被我带偏,我的不一定是最佳的
// 练习
// 1. 获取⽤户信息 https://api.github.com/users/{username}
// 2. 获取仓库列表信息 https://api.github.com/users/{username}/repos
// 3. 用户与仓库列表信息:普通读取json、Unmarshal转结构体⽅式解析、gjson读取
// 4. 用户与仓库列表信息:格式化输出到控制台
// 5. 仓库列表信息保存到本地 JSON ⽂件中。
//这里就固定拿仓库列表信息如下信息:
// (也可以随便获取你想要的字段)
// 用户信息{login、id、url、name、email}
// 仓库列表信息{name、owner.login、description}
- myMarshalIndent:为了方便格式化,我自己写了一个格式化函数方便不同方式保存的时候进行格式化
格式化都需要先转到map中存储才能够格式化正常的json数据出来,格式化好了就任意你想干啥就干啥了 - 需要注意的细节:
有的json他是列表包裹着[],所以转的时候要注意判断用map[string]interface{}还是[]map[string]interface{} - json.MarshalIndent:他可以对map列表进行格式化的,因为那样也时一个正常的json数据,只不过你需要用
[]map[string]interface{}列表类型进行存储(这里是一个很重要的细节,开发过程中如果不注意很容易导致崩溃)
我用了三个函数完成这个练习:
- normalGetJson:普通读取,就是解析出来后整个data就直接write到文件中
- UnmarshalToStruct:Unmarshal转结构体⽅式解析,这里使用了上面学到的
SetSuccessResult,给到结构体后进行解析,这样也很方便 - gjsonOutput:这里就是使用gjson了,gjson很方便,但是面对比较多字段提取的时候还是比较繁琐。
这里复习了一个细节:map想要后续不断地赋值的话就需要进行make空间出来才行,如果是[]map的话需要给定一个空间范围,0也行,你要说明这是一个切片。如果你只是单单定义一个map变量或者map切片变量,后续是无法使用的。
还有一个细节就是:make出来的空间是固定的,如果你要make出来的空间作为一个临时变量赋值给其他变量的时候要注意了,用了一个空间就不要继续用了,因为你将一个空间给了多个变量的话,那么那些变量都指向你这一个空间,那么他们的值其实都一样。
运行结果:这里就放几个保存出来的文件截图
-
normalGetJson:

-
UnmarshalToStruct

-
gjsonOutput

示例代码:
// 用户信息{login、id、url、name、email}// 仓库列表信息{name、owner.login、description}func gjsonOutput(username string) {//gjson就十分简单了,只需要拿到响应json数据即可取出来看mapUserData := make(map[string]interface{}) //用户信息存储//仓库信息存储,// 由于仓库是数组列表所以要给一个初始长度// 因为可能仓库为空的,所以就初始化为0即可mapReposData := make([]map[string]interface{}, 0)fmt.Println("-------------------用户信息-------------------")client := req.C()resp, err := client.R().SetPathParam("username", username).Get("https://api.github.com/users/{username}")if err != nil {log.Println("代码请求失败:", err)}//gjson想要写入文件就只能转储到struct或者map中mapUserData["login"] = gjson.Get(resp.String(), "login").String()mapUserData["id"] = gjson.Get(resp.String(), "id").String()mapUserData["url"] = gjson.Get(resp.String(), "url").String()mapUserData["name"] = gjson.Get(resp.String(), "name").String()mapUserData["email"] = gjson.Get(resp.String(), "email").String()data, err := json.MarshalIndent(mapUserData, "", "\t")if err != nil {log.Println("格式化失败:", err)}fmt.Println(string(data))// test := gjson.Get(resp.String(), "login")// fmt.Println(test)fmt.Println("---------------------------------------------")fmt.Println("-------------------仓库信息-------------------")client = req.C()resp, err = client.R().SetPathParam("username", username).Get("https://api.github.com/users/{username}/repos")if err != nil {log.Println("代码请求失败:", err)}// 仓库列表信息{name、owner.login、description}arr := gjson.Get(resp.String(), "#.name")for i, j := range arr.Array() {//一定要放到这里来,因为make指向同一个空间,// 如果你在for外面定义mapTmpRepos造成取到的值会全部变成最后一个值,// 因为同一个空间他会同步改变你map切片append里面所有的内容,// 因为同一个空间嘛mapTmpRepos := make(map[string]interface{})mapTmpRepos["name"] = j.String()mapTmpRepos["login"] = gjson.Get(resp.String(), (strconv.Itoa(i) + ".owner.login")).String()mapTmpRepos["description"] = gjson.Get(resp.String(), (strconv.Itoa(i) + ".description")).String()mapReposData = append(mapReposData, mapTmpRepos)}data, err = json.MarshalIndent(mapReposData, "", "\t")if err != nil {fmt.Println("格式化失败:", err)}fmt.Println(string(data)) //格式化的内容打印到终端file, err := os.OpenFile("gjson.json", os.O_CREATE|os.O_RDWR|os.O_RDWR, 0666)if err != nil {log.Println("打开文件失败:", err)}_, err = file.Write(data)if err != nil {log.Println("导出json失败:", err)}}
Cookie
请求级别:
- SetCookies
SetCookies(&http.Cookie{Name: "hacker",Value: "aaa",
})
全局级别:
- SetCommonCookies
SetCommonCookies(&http.Cookie{Name: "Global",Value: "dddd",
})
默认行为
就是当你请求的服务端响应了set-cookie回来后,当你再次请求的时候就会携带上这个set-cookie回来的cookie键值去请求。
禁⽤Cookie
- SetCookieJar(nil)
存储Cookie
安装
go get -u github.com/juju/persistent-cookiejar
使用
func saveCookies() {jar, err := cookiejar.New(&cookiejar.Options{Filename: "cookies.json",})if err != nil {log.Println("保存失败")}defer jar.Save()client := req.C().SetCookieJar(jar).DevMode()client.R().Get("http://www.baidu.com")}
证书校验
无视风险
针对一些不安全的网站请求可能会请求失败,所以需要忽略证书的校验
两种方式可以忽略:
client := req.C().DevMode().EnableDumpAllWithoutResponse()
//忽略证书风险
//第一种
//client.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true})
//第二种
client.TLSClientConfig.InsecureSkipVerify = true
_, err := client.R().Get("https://self-signed.badssl.com/")
if err != nil {fmt.Println("代码请求失败:", err)
}
配置证书
配置好风险站点的证书即可访问风险站点
证书需要访问网站的时候在浏览器的小锁中下载即可(具体不演示了,自行百度网站证书如何下载)
- 证书文件配置
client := req.C().DevMode().EnableDumpAllWithoutResponse()
//可以同时配置多个网站的证书
client.SetRootCertsFromFile("cert1.crt","cert2.crt","cert3.crt")
- 证书内容配置
在下载了证书之后,可以编辑证书将里面的内容配置进来也行
client := req.C().DevMode().EnableDumpAllWithoutResponse()
client.SetRootCertFromString("-----BEGIN CERTIFICATE-----")
Auth身份认证
- SetBasicAuth
- SetDigestAuth
区别:
一个Basic认证,一个Digest认证
Digest认证比较安全,请求被拦截了攻击者无法直接获取密码
但是Basic的请求被拦截了就是直接获取到密码
服务端支持哪一个?
检查WWW-Authenticate响应头,返回Basic 还是 Digest就知道支持哪一个。
func authHttp() {client := req.C().DevMode().EnableDumpAllWithoutResponse()client.R().SetBasicAuth("username", "password").Get("https://httpbin.org/uuid")client2 := req.C().DevMode().EnableDumpAllWithoutResponse()client2.R().SetDigestAuth("username2", "password2").Get("https://httpbin.org/uuid")}
文件上传下载
上传文件
- SetFile
- SetFiles:接收map类型,上传多个文件
- SetUploadCallback:显示上传进度
func uploadFileHttp() {//简单上传client := req.C().DevMode().EnableDumpAllWithoutResponse()callback := func(info req.UploadInfo) { //显示上传进度fmt.Printf("\n文件名:%q\n已上传:%.2f%%\n",info.FileName,float64(info.UploadedSize)/float64(info.FileSize)*100.0)}client.R().//SetFile("filename", "cookies.json").SetFiles(map[string]string{"test": "test.txt","test2": "test2.txt","test3": "test3.txt",}).SetUploadCallback(callback). //使用该函数:显示上传进度Post("https://httpbin.org/post")}
下载文件
- SetOutputFile:这里是指定下载的文件路径
- SetOutputDirectory:设置下载的默认路径,即SetOutputFile可以只给文件名,自动存在该路径下
- SetDownloadCallback:显示下载进度
func downloadFileHttp() {client := req.C() //.DevMode().EnableDumpAllWithoutResponse()callback := func(info req.DownloadInfo) {if info.Response.Response != nil { //响应不为空fmt.Printf("\n已下载:%.2f%%\n",float64(info.DownloadedSize)/float64(info.Response.ContentLength)*100.0)}} client.R().//这里是指定文件路径SetOutputFile("./baidu.html").Get("http://127.0.0.1/xxx.txt")client2 := req.C().//这里可以设置默认下载目录,后面直接download的时候就不用指定路径了,给文件名即可SetOutputDirectory("./").DevMode().EnableDumpAllWithoutResponse()client2.R().SetOutputFile("baidu2.html").SetDownloadCallback(callback).Get("http://127.0.0.1/xxx.txt")}
多线程下载练习
- NewParallelDownload:创建一个多线程下载客户端
- 其他函数在注释中标明了。
func threatDownload() {client := req.C()err := client.NewParallelDownload("http://xxxxx.xxxx.xxx/xxx.iso").SetConcurrency(5). //设置 5 个线程 并行下载SetFileMode(0777). //设置 文件权限(可读可写可执行)。SetOutputFile("xxx.iso"). //设定最终 存储文件名SetSegmentSize(1024 * 1024 * 5). //每个线程下载 5MB 的数据块SetTempRootDir("./tmp"). //这个是下载的时候指定的临时存储目录Do()if err != nil {log.Println("下载失败:", err)return}}
相关文章:
Go红队开发—web网络编程
文章目录 web网络编程Req快速请求 调试DevModeDebugLogTraceInfo瓶颈分析 控制请求与响应控制请求的字段内容控制调试打印的内容分开dump请求与响应部分请求体设置 作用范围级别设置参数查询URL 路径参数表单请求设置请求头设置 判断响应状态码解析数据SetSuccessResultgjson响…...
libwebsockets实现异步websocket客户端,服务端异常断开可重连
libwebsockets websocket客户端基本流程网上都有,我只额外优化了重连机制。 在服务器异常断开时不触发LWS_CALLBACK_CLOSED或LWS_CALLBACK_CLIENT_CONNECTION_ERROR,导致无法自动重连 通过定时检查链接是否可写入判断链接是否有效 // 判断wsi是否可用if …...
轻量级模块化前端框架:快速构建强大的Web界面
轻量级模块化前端框架:快速构建强大的Web界面 在当今快节奏的Web开发环境中,选择一个高效且灵活的前端框架至关重要。UIkit 是一个轻量级的模块化前端框架,旨在帮助开发者快速构建功能强大且响应迅速的Web界面。 UIkit提供了丰富的组件和工…...
qt+opengl 播放yuv视频
一、实现效果 二、pro文件 Qt widgets opengl 三、主要代码 #include "glwidget.h"GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent) {connect(&m_timer, &QTimer::timeout, this,[&](){this->update();});m_timer.start(1000/33); }v…...
UI自动化:poium测试库
以下是关于 poium 测试库 的详细介绍,涵盖其核心功能、使用方法及与原生 Selenium 的对比,帮助快速掌握这一工具: 1. poium 简介 定位:基于 Selenium 的 Page Object 模式增强库,专注于简化元素定位和页面操作。 核心…...
树莓集团落子海南,如何重构数字产业生态体系
树莓集团在海南的布局,是其整体商业战略中的关键一环。这背后,是对政策机遇、产业协同、以及区域优势的深度考量。 政策机遇 海南自贸港建设带来前所未有的政策红利,包括贸易、投资、资金等方面的自由便利。树莓集团紧抓这一机遇࿰…...
5G基本概念
作者:私语茶馆 1. 5G应用场景概述 1.1.5G应用场景 ITU域2015年定义了三大应用场景:eMBB(增强型移动宽带)、uRLLC(低时延高可靠通信)、mMTC(海量物联网通信); emBB:Enhanced Mobile Broadband ,移动互联网应用,是4G MBB(移动宽带)的升级,主要侧重于网络速率、带…...
PH热榜 | 2025-03-12
1. Fluently 标语:开始说英语,就像说你的母语一样流利。 介绍:想象一下,有一个像人类一样的英语教练,全天候在线、价格却便宜15倍。这就是 Fluently 🚀 纠正你的错误,提升你的词汇量、发音和语…...
Python Web项目的服务器部署
一.部署运行 1.虚拟环境的安装:(一行一行运行) wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh bash miniconda.sh -b -p /opt/miniconda3 echo export PATH"/opt/miniconda3/bin:$PAT…...
[项目]基于FreeRTOS的STM32四轴飞行器: 八.遥控器摇杆
基于FreeRTOS的STM32四轴飞行器: 八.遥控器摇杆 一.摇杆数据的扫描二.处理摇杆数据三.微调按键处理 一.摇杆数据的扫描 下面摇杆初始化时,启动了ADC-DMA进行了采集,已经开始转换直接将数据通过DMA存入buff数组中: static uint16_t buff[4] …...
附下载 | 2024 OWASP Top 10 基础设施安全风险.pdf
《2024 OWASP Top 10 基础设施安全风险》报告,由OWASP(开放网络应用安全项目)发布,旨在提升企业和组织对基础设施安全风险、威胁与漏洞的意识,并提供高质量的信息和最佳实践建议。报告列出了2024年最重要的10大基础设施…...
Pytorch的一小步,昇腾芯片的一大步
Pytorch的一小步,昇腾芯片的一大步 相信在AI圈的人多多少少都看到了最近的信息:PyTorch最新2.1版本宣布支持华为昇腾芯片! 1、 发生了什么事儿? 在2023年10月4日PyTorch 2.1版本的发布博客上,PyTorch介绍的beta版本…...
C语言操作MySQL从入门到精通
大家好,我是 V 哥。今天给大家整理的内容是关于使用 C 语言操作 MySQL 数据库的详细介绍,从入门到精通,并配有案例代码和注释,帮助小白快速上手。 基本操作 1. 环境准备 在开始之前,你需要安装 MySQL 数据库和 MySQ…...
【从零开始学习计算机科学】编译原理(五)语法制导翻译
【从零开始学习计算机科学】编译原理(五)语法制导翻译 语法制导翻译语法制导定义SDDSDD的求值顺序两类重要的SDD语法制导的翻译方案SDTSDT的实现L属性定义的SDT左递归翻译方案语法制导翻译 语法表述的是语言的形式,或者说是语言的样子和结构。而程序设计语言中另一方面,是…...
uniapp uview 1.0 跨域h5配置多个代理、如何请求接口
参考文章:uniapp uView1.0跨域h5配置多个代理 官方手册:http 请求 项目中使用: 参考其他博主的文章是在manifest.json中配置代理,但在官方的手册中是直接在script请求的,我尝试请求了下没问题,上线后也不…...
化工厂防爆气象站:为石油化工、天然气等领域提供安全保障
【TH-FB02】在石油化工、天然气等高危行业中,安全生产是至关重要的。这些行业常常面临着易燃易爆、有毒有害等潜在风险,因此,对气象条件的监测和预警显得尤为重要。化工厂防爆气象站作为一种专门设计用于这些特殊环境的气象监测设备ÿ…...
Android Glide 缓存模块源码深度解析
一、引言 在 Android 开发领域,图片加载是一个极为常见且关键的功能。Glide 作为一款被广泛使用的图片加载库,其缓存模块是提升图片加载效率和性能的核心组件。合理的缓存机制能够显著减少网络请求,降低流量消耗,同时加快图片显示…...
Mac安装Neo4j图数据库
通过Homebrew 安装(推荐) 打开mac终端: 1. 安装 Homebrew(如果尚未安装) /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"2. 安装 Neo4j brew insta…...
《A Gentle Introduction to Graph Neural Networks》-GNN的综述性论文
目录 一、什么数据可以表示成一张图 (1)什么是图? (2)如何表示图的属性 (3)images as graphs(将图片表示为图) (4)text as graphs(…...
[023-01-40].第40节:组件应用 - OpenFeign与 Sentinel 集成实现fallback服务降级
SpringCloud学习大纲 一、需求说明: 需求1:通过fallback属性进行统一配置 a.问题分析: 1.需要实现cloudalibaba-consumer-nacos-order83模块通过OpenFeign调用cloudalibaba-provider-payment9001 83服务通过OpenFeign调用 9001微服务&…...
设计模式-结构型模式-装饰器模式
概述 装饰器模式 : Decorator Pattern : 是一种结构型设计模式. 作用 : 允许你动态地给对象添加功能或职责,而无需修改其原始类的代码,非常的符合 开闭原则。 实现思路 :通过创建一个包装对象(即装饰器),来…...
RK3588 编译 openssl
在编译 OpenSSL 时,你需要确保你的系统环境已经配置好了所有必要的依赖和编译工具。下面是一般步骤和一些常见问题的解决方案,特别是在使用 RK3588 这类的 ARM 处理器上。 1. 安装依赖 首先,你需要安装编译 OpenSSL 所需的依赖。这通常包括编译器(如 GCC)、make 工具、Per…...
Git前言(版本控制)
1.Git 目前世界上最先进的分布式版本控制系统。 git官网:https://git-scm.com/ 2.版本控制 2.1什么是版本控制 版本控制(Revision control)是一种在开发的过程中用于管理我们对文件、目录或工程等内容修改历史,方便查看更改历史记录备份以便恢复以前…...
visual studio配置opencv
文章目录 step1 下载opencvstep2 配置包含目录step 3 配置链接器step4 配置环境变量并重启vs2022step5 检查代码 step1 下载opencv 下载 opencv-4.8.0-windows.exe https://cloud.189.cn/web/share?codefUnqEb7naUra step2 配置包含目录 step 3 配置链接器 step4 配置环境变…...
docker修改daemon.json文件后无法启动
1.问题描述 使用阿里云docker镜像安装的docker,安装成功后默认可以启动。但是修改daemon.json配置后docker服务无法启动,提示如下错误: 从上图发现,docker服务默认使用阿里docker镜像仓库 2.解决方法 根据提示找到docker服务目…...
Linux网络:网络与操作系统1
本文是介绍网络的基本结构,以及和OS之间有什么关系 OSI七层模型 引入 使用网络是为了解决信息的长距离传送,那就需要解决四个问题: 接收方如何使用数据传输的可靠性主机如何定位数据包在局域网如何转发 人们选择用网络协议(t…...
Manus(一种AI代理或自动化工具)与DeepSeek(一种强大的语言模型或AI能力)结合使用任务自动化和智能决策
一、Manus与DeepSeek差异 十分好奇DeepSeek和Manus究竟谁更厉害些,DeepSeek是知识型大脑,Manus则是全能型执行者。即DeepSeek专注于语言处理、知识整合与专业文本生成。其核心优势在于海量参数支持的深度学习和知识推理能力,例如撰写论文、润…...
Python个人学习笔记(14):函数(匿名函数、内置函数(下)、三元表达式)
九、匿名函数 lambda表达式 语法规则: 变量 lambda 参数1,参数2,…:返回值 例:用lambda简化下述操作 def func(a,b):return ab ret func(1, 2) print(ret)代码: fn lambda a,b:ab print(fn) print(fn(12,13))结果: <fun…...
姚安娜新剧瘦了一圈,《仁心俱乐部》急诊医生顾诗宜在线上岗
《仁心俱乐部》在芒果 TV 播出,湖南卫视金鹰独播剧场也随之播出,这一剧集受到了不少观众的关注。姚安娜在剧中饰演的急诊科医生顾诗宜,她为患者检查身体时动作娴熟,与患者沟通时展现出的耐心和专注,都展现出很高的专业…...
【PyCharm】Python和PyCharm的相互关系和使用联动介绍
李升伟 整理 Python 是一种广泛使用的编程语言,而 PyCharm 是 JetBrains 开发的专门用于 Python 开发的集成开发环境(IDE)。以下是它们的相互关系和使用联动的介绍: 1. Python 和 PyCharm 的关系 Python:一种解释型、…...
