mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-10-05 08:46:59 +08:00

对一般用户而言,还是需要使用Info等级 来了解一下 一般的 日志情况,等到使用熟练之后,且确认运行没有错误后, 可以自行调为 warning 来提升性能 发现 bubble包 还自己引入了 命令行参数,这十分不可取,所以我们还是直接使用其代码。 将其它包中 的 命令行参数 统一 移动 到 cmd/verysimple 中;tls lazy 特性因为还在 调试阶段,所以 命令行参数 仍然放到 v2ray_simple 包中。
170 lines
4.0 KiB
Go
170 lines
4.0 KiB
Go
package netLayer
|
||
|
||
import (
|
||
"io"
|
||
"net"
|
||
"sync"
|
||
"syscall"
|
||
|
||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||
)
|
||
|
||
//经过测试,网速越快、延迟越小,越不需要readv, 此时首包buf越大越好, 因为一次系统底层读取就会读到一大块数据, 此时再用readv分散写入 实际上就是反效果; readv的数量则不需要太多
|
||
|
||
//在内网单机自己连自己测速时,readv会导致降速.
|
||
|
||
const (
|
||
readv_buffer_allocLen = 8
|
||
ReadvSingleBufLen = 4096
|
||
|
||
DefaultReadvOption = true
|
||
)
|
||
|
||
var (
|
||
// readv pool, 缓存 mr和buffers,进一步减轻内存分配负担
|
||
readvPool sync.Pool
|
||
|
||
UseReadv bool
|
||
)
|
||
|
||
func init() {
|
||
|
||
readvPool = sync.Pool{
|
||
New: newReadvMem,
|
||
}
|
||
|
||
//预先放进去两个
|
||
|
||
readvPool.Put(newReadvMem())
|
||
readvPool.Put(newReadvMem())
|
||
}
|
||
|
||
// 缓存 readvMem 以及对应分配的系统相关的 utils.SystemReadver.
|
||
// 使用 readvMem的最大好处就是 buffers 和 mr 都是不需要 释放的.
|
||
// 因为不需释放mr, 所以也就节省了多次 mr.Init 的开销.
|
||
// 该 readvMem 以及 readvPool 专门服务于 TryCopy 函数.
|
||
type readvMem struct {
|
||
buffers [][]byte
|
||
mr utils.SystemReadver
|
||
}
|
||
|
||
func allocReadvBuffers(mr utils.SystemReadver, len int) [][]byte {
|
||
bs := make([][]byte, len)
|
||
|
||
for i := range bs {
|
||
// 这里单独make,而不是从 其它pool中获取, 这样可以做到专用
|
||
bs[i] = make([]byte, ReadvSingleBufLen)
|
||
}
|
||
mr.Init(bs, ReadvSingleBufLen)
|
||
return bs
|
||
}
|
||
|
||
func newReadvMem() any {
|
||
mr := utils.GetReadVReader()
|
||
return &readvMem{
|
||
mr: mr,
|
||
buffers: allocReadvBuffers(mr, readv_buffer_allocLen),
|
||
}
|
||
}
|
||
|
||
func get_readvMem() *readvMem {
|
||
return readvPool.Get().(*readvMem)
|
||
|
||
}
|
||
|
||
//将创建好的rm放回 readvPool
|
||
func put_readvMem(rm *readvMem) {
|
||
rm.buffers = utils.RecoverBuffers(rm.buffers, readv_buffer_allocLen, ReadvSingleBufLen)
|
||
readvPool.Put(rm)
|
||
}
|
||
|
||
/*
|
||
//目前我们使用内存池,所以暂时不需要手动释放内存,
|
||
//如果真需要手动申请、释放,可参考 https://studygolang.com/articles/9721
|
||
func (rm *readvMem) destroy() {
|
||
rm.mr.Clear()
|
||
rm.mr = nil
|
||
rm.buffers = nil
|
||
}*/
|
||
|
||
/* readvFrom 用于读端实现了 readv但是写端的情况,比如 从socks5读取 数据, 等裸协议的情况。
|
||
|
||
若 rm 未给出,会使用 get_readvMem 来初始化 缓存。
|
||
|
||
返回错误时,依然会返回 原buffer 或者 在函数内部新分配的buffer.
|
||
|
||
本函数不负责 释放分配的内存. 因为有时需要重复利用缓存。
|
||
|
||
小贴士:将该 [][]byte 写入io.Writer的话,只需使用 net.Buffers.WriteTo方法, 即可自动适配writev。
|
||
不过实测writev没什么太大效果,还会造成不稳定。因为 WriteTo会篡改cap
|
||
|
||
TryCopy函数使用到了本函数 来进行readv相关操作。
|
||
*/
|
||
func readvFrom(rawReadConn syscall.RawConn, rm *readvMem) ([][]byte, error) {
|
||
|
||
if rm == nil {
|
||
rm = get_readvMem()
|
||
}
|
||
|
||
allocedBuffers := rm.buffers
|
||
|
||
var nBytes uint32
|
||
err := rawReadConn.Read(func(fd uintptr) bool {
|
||
n, e := rm.mr.Read(fd)
|
||
if e != nil {
|
||
return false
|
||
}
|
||
|
||
nBytes = n
|
||
return true
|
||
})
|
||
if err != nil {
|
||
|
||
return allocedBuffers, err
|
||
}
|
||
if nBytes == 0 {
|
||
return allocedBuffers, io.EOF
|
||
}
|
||
|
||
nBuf := utils.ShrinkBuffers(allocedBuffers, int(nBytes), ReadvSingleBufLen)
|
||
|
||
return allocedBuffers[:nBuf], nil
|
||
}
|
||
|
||
//依次试图使用 readv、ReadBuffers 以及 原始 Read 读取数据
|
||
func ReadBuffersFrom(c io.Reader, rawReadConn syscall.RawConn, mr utils.MultiReader) (buffers [][]byte, err error) {
|
||
|
||
if rawReadConn != nil {
|
||
readv_mem := get_readvMem()
|
||
defer put_readvMem(readv_mem)
|
||
|
||
buffers, err = readvFrom(rawReadConn, readv_mem)
|
||
|
||
} else if mr != nil {
|
||
return mr.ReadBuffers()
|
||
} else {
|
||
packet := utils.GetPacket()
|
||
var n int
|
||
n, err = c.Read(packet)
|
||
if err != nil {
|
||
return
|
||
}
|
||
buffers = append(buffers, packet[:n])
|
||
}
|
||
return
|
||
}
|
||
|
||
func IsConnGoodForReadv(c net.Conn) (r int, rawReadConn syscall.RawConn, mr utils.MultiReader) {
|
||
rawReadConn = GetRawConn(c)
|
||
var ok bool
|
||
if rawReadConn != nil {
|
||
r = 1
|
||
return
|
||
|
||
} else if mr, ok = c.(utils.MultiReader); ok {
|
||
r = 2
|
||
return
|
||
}
|
||
return
|
||
}
|