go 后端笔记2 Go 语言实战案例

55 阅读2分钟

猜谜游戏

随机数

  • 随机数使用 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 为 0x05
  • NMETHODS:客户端支持的认证方法数量
  • METHODSNMETHODS 个字节,00 表示不需要认证,02 表示用户名/密码认证 需要返回服务器选择的鉴权认证方式,通过 Write 输出一组字节
  • VER:协议版本,socks5 为 0x05
  • METHOD:服务器选定的认证方法

请求

请求报文:

  • VER:协议版本,socks5 为 0x05
  • CMD:请求类型,CONNECT 请求为 0x01
  • RSV:0x00,保留字符
  • ATYP:目标地址类型,决定 ADDR 字段长度
    • IPv4 地址:0x01,长度 4 字节
    • 域名:0x03,ADDR 为一个不定长度的字符串
  • DST.ADDR:目标地址,若 ATYP 为域名时类型第一个字节是域名长度(byte数组长度)
  • DST.PORT:目标端口,长度 2 字节 响应报文:
  • VER:协议版本,socks5 为 0x05
  • REP:00 表示 succeeded
  • RSV:保留字段,值为 0x00
  • ATYPEBND.ADDR 类型
  • BND.ADDR:服务器绑定地址
  • BND.PORT:服务器绑定端口

relay

代理与服务器建立连接,在客户端与服务器之间传递数据

  • 使用 net.Dial("tcp", url) 建立网络连接
  • 使用 io.Copy 复制读写缓冲区
  • 使用管道将输入拷贝到 dial,再将 dial 输出到 client(context.WithCancel