猜谜游戏
随机数
- 随机数使用
math/rand包生成,使用rand.Seed()设置随机数种子 - 通常使用当前时间作为随机数种子,
time.Now()可获取当前时间,通常转为nano数字作为种子
rand.Seed已过时,使用rand.New(rand.NewSource(seed))创建Rand对象代替全局的rand,方法调用与 rand 相同
用户输入
通过 os.Stdin 读入用户控制台输入,可以使用 bufio.NewReader 包装一下
Reader.ReadString(char):读取输入,直到某个字符
[!caution] 注意
ReadString参数中的字符也会在读出的字符串中,如\n,通常需要使用strings.TrimSuffix进一步处理
在线词典
- 可使用在线工具 根据 curl 命令(可以在浏览器开发人员工具的网络标签复制)生成网络请求代码
defer:函数结束时自下而上执行,用于清理环境,关闭资源等
Socks5 服务器
服务器监听
使用 net.Listen() 开启一个创建服务器对象并监听某个地址和端口
server.Accept()获取一个请求,返回(client, error)- 使用
go 函数调用开启一个并发任务。go 并发是一种协程,上下文切换比线程更轻量 client是一个net.Conn对象,也可以使用bufio.NewReader包装
认证
首先接收客户端提供的认证方式,报文信息如下:
VER:协议版本,socks5 为 0x05NMETHODS:客户端支持的认证方法数量METHODS:NMETHODS个字节,00 表示不需要认证,02 表示用户名/密码认证 需要返回服务器选择的鉴权认证方式,通过Write输出一组字节VER:协议版本,socks5 为 0x05METHOD:服务器选定的认证方法
请求
请求报文:
VER:协议版本,socks5 为 0x05CMD:请求类型,CONNECT 请求为 0x01RSV:0x00,保留字符ATYP:目标地址类型,决定ADDR字段长度- IPv4 地址:0x01,长度 4 字节
- 域名:0x03,ADDR 为一个不定长度的字符串
DST.ADDR:目标地址,若 ATYP 为域名时类型第一个字节是域名长度(byte数组长度)DST.PORT:目标端口,长度 2 字节 响应报文:VER:协议版本,socks5 为 0x05REP:00 表示 succeededRSV:保留字段,值为 0x00ATYPE:BND.ADDR类型BND.ADDR:服务器绑定地址BND.PORT:服务器绑定端口
relay
代理与服务器建立连接,在客户端与服务器之间传递数据
- 使用
net.Dial("tcp", url)建立网络连接 - 使用
io.Copy复制读写缓冲区 - 使用管道将输入拷贝到 dial,再将 dial 输出到 client(
context.WithCancel)