@
dzdh 伪代码如下
// 分桶减少锁碰撞
// conn 对应了 host 。https keepalive 的一个连接只能是唯一的 host 。 这与 http 不同
// bucketMap := [30]map[net.Conn]string
// bucketMapMutex:=[30]sync.Mutex
cfg := &tls.Config{
InsecureSkipVerify: true,
MinVersion: tls.VersionTLS12,
GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
// 通过 info.Conn.LocalAddr() 确定 bucketMapMutex 分桶
// bucketMap[info.Conn]=info.ServerName // 连接与 host 对应好
return GetAndCreateCert(info.ServerName)
},
}
ln, err := net.Listen("tcp", ":12345")
assert(err)
lsn := tls.NewListener(ln, cfg)
for {
c, _ := lsn.Accept()
go func(conn net.Conn) /* 这个协程可以用协程池复用*/{
// 通过 info.Conn.LocalAddr() 确定 bucketMapMutex 分桶
//serverName:=bucketMap[idx][conn]
//addr:=serverName// 根据 serverName 确定后面的地址,如果无差别沦陷
remote, err := net.Dial("tcp", addr)
assert(err)// 做好 error 呴错误处理
// conn 设置 keepalive retmote 设置好 keepalive 建议搞成配置
// 优化合理设计,使一条代理只需要两个协程,做到如下内容:
// 1. 再包装一层 reader weiter 方便设置断开时间 conn.SetReadDeadline()
// 2. 原子操作协调断开
// connFlag atomic.Int32
// remoteFlag atomic.Int32
go func() {
// 3. 加上异常处理 断开 defer conn.Close remote.Close
io.Copy(conn, remote)
}()
go func() {
// 加上异常处理 断开 defer conn.Close remote.Close
io.Copy(remote, conn)
}()
}(c)
}