常用API实践 | 青训营笔记

108 阅读43分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天

前言

大家好呀,这是我参加青训营伴学笔记创作活动的第 4 天,如存在问题,烦请各位斧正!

注意:有一点要说明,时间处理和数字解析那一块,我放进去的图片说是超过了最大字符限制,所以无法展示了,如有需要,请各位与我联系。

其中包括一些关键代码,如有需要可以跟我要笔记原文。

使用网站进行代码生成案例

生成请求代码

1)先去一个在线词典打开开发者工具随便发一个翻译请求。(如彩云翻译https://fanyi.caiyunapp.com/#/

2)找到dict文件/post 方式的请求,右键请求 复制cURL。(请求头等信息)

3)将cURL放到代码生成网站,生成对应语言代码(如https://curlconverter.com/go/

代码分为"创建请求、设置请求头、发起请求、读取响应"四步。(如下代码,设置请求头略)

<字符超过最大限度>

<字符超过最大限度>

优化

1)定义一个结构体,以此来定制请求参数:(红色代码为删除,绿色为新增)

<字符超过最大限度>

2)解析请求体(自动生成一个结构体,属性与返回的response一一对应)(扔进去json转成go结构体:oktools.net/json2go)

<字符超过最大限度>

3)建议在这之前加上这三行代码,以便更好的排查问题

<字符超过最大限度>


SOCKS5实现代理服务器

概述

1)SOCKS5是一个代理协议,它用于在客户端和服务器之间建立一个代理连接(使用TCP/IP协议通讯,也支持UDP),它是明文传输的。

2)它可以用于保护用户隐私、穿透防火墙、提高网络连接速度等。它是 Socks 协议的第五个版本,具有比先前版本更高的安全性和功能性。

原理

设置代理服务器之后,访问网站的流程会变得复杂一些。

首先是浏览器和 SOCKS5 代理建立 TCP 连接,代理再和真正的服务器建立 TCP 连接。

这里可以分成四个阶段,握手阶段、认证阶段、请求阶段、 relay 阶段。

<字符超过最大限度>

1)第一个握手阶段,浏览器会向 SOCKS5 代理发送请求,内容包括协议的版本号,还有支持的认证的种类等,SOCKS5 服务器会选中一个认证方式,返回给浏览器。

如果返回的是 00 的就代表不需要认证,返回其他类型的话会开始认证流程。

2)第三个阶段是请求阶段,认证通过之后浏览器会向 SOCKS5 服务器发起请求。

主要信息包括版本号,请求的类型,一般主要是 connection 请求,就代表代理服务器要和某个域名或者某个 IP 地址某个端口建立 TCP 连接。

代理服务器收到响应之后,会真正和后端服务器建立连接,然后返回一个响应。

3)第四个阶段是 relay 阶段。此时浏览器会正常发送请求,然后代理服务器接收到请求之后,会直接把请求转换到真正的服务器上。

当真正的服务器以后返回响应的话,它也会把请求转发到浏览器这边。

一个简单的socket编程案例

<字符超过最大限度>

认证阶段

1、认证阶段下,浏览器会给代理服务器发送一个包,这个包有三个字段。

1)第一个字段,version 协议版本号,固定是5。占一个字节

2)第二个字段,methods 认证的方法数目 即下一个字段的长度。占一个字节

3)第三个字段,表示客户端支持的验证方式,可以有多种。占1-255个字节(00代表不需要认证,02代表用户名密码认证)

2、代码逻辑

1)先定义一些常量,方便对比:

<字符超过最大限度>

2)我们定义一个auth函数,在process函数中调用,将自己创建的reader传入,可以借助它来依次读取认证的各个字段:

<字符超过最大限度>

最后代理服务器还需要返回一个 response,返回包括 两个字段,一个是 version ,一个是 method。

<字符超过最大限度>

请求阶段

1、请求阶段,浏览器会发送一个包,包里面包含如下6个字段:

(1)version 版本号 (2)command 请求的类型,0x01表示connect请求 (3)RSV 保留字段,值为0x00

(4)atype 目标地址类型(可能是IPV4、IPV6、域名) (5)addr 地址 (6)port 端口号

2、实现一个和 auth 函数类似的 connect 函数,同样在process 里面去调用,然后需要逐个去读取这些字段并校验。

1)使用ReadFull将字节读到切片里,然后逐个判断ver和cmd(跟上一个阶段的判断方式一样,对应的常量也是上一个阶段定义的)。

<字符超过最大限度>

2)atyp的判断方式比较特别:

<字符超过最大限度>

3)最后同样通过conn.Write写会去一些数据。

relay阶段

1)直接用 net.dial 和真正的服务器端建立一个 TCP 连接,建立完连接之后要是没有出错,第一时间加defer关闭连接。

<字符超过最大限度>

2)接下来需要建立浏览器和下游服务器的双向数据转发。

<字符超过最大限度>

(1)标准库的 io.copy 可以实现一个单向数据转发,双向转发需要启动两个 goroutinue(go关键字)。

(2)我们需要等待两个双向转发的结束,才能到return,不然连接会提前关闭,所以使用到标准库里面的一个context机制,

用 context 连with cancel来创建一个context,在最后等待 ctx.Done() ,只要cancel被调用(幂等的), ctx.Done就会立刻返回。