修复一个open too many files
- 作者:
- 淡白
- 创建时间:
- 2021-09-09 18:00:03
- Go socket
摘要:在使用socks5代理客户端时,发现很多连接没有被正常关闭的问题。问题出现在代码中的两个地方。首先,在client.go文件中,当代理类型不为http时,会执行安全信道建立的代码。其次,在cryptogram.go文件中的copy方法中,会进行加密io复制。当一方连接断开时,另一方连接可能不会被正常关闭,导致锁一直没有释放。本地连接也一直没有关闭,从而打开了太多连接并出现报错。为了解决这个问题,对代码进行了修改。首先,在cryptogram.go文件的copy方法中,增加了对连接的关闭操作。其次,在client.go文件中,将连接的关闭放在copy方法内部,当一方连接被关闭时,关闭两个连接,另一个拷贝就能感知到并读取错误并正常关闭并退出。这样就解决了连接没有正常关闭的问题。
在使用socks5代理客户端发现,很多连接没有被正常关闭。
在文件client.go
中当代理类型不为http
时会执行以下代码
// 和远程端建立安全信道
wg := new(sync.WaitGroup)
wg.Add(2)
// 本地的内容copy到远程端
go func() {
defer wg.Done()
SecureCopy(localClient, dstServer, auth.Encrypt)
}()
// 远程得到的内容copy到源地址
go func() {
defer wg.Done()
SecureCopy(dstServer, localClient, auth.Decrypt)
}()
wg.Wait()
在cryptogram.go
中的copy方法如下
// 加密io复制,可接收加密函数作为参数
func SecureCopy(src io.ReadWriteCloser, dst io.ReadWriteCloser, secure func(b []byte) error) (written int64, err error) {
size := 1024
buf := make([]byte, size)
for {
nr, er := src.Read(buf)
secure(buf)
if nr > 0 {
nw, ew := dst.Write(buf[0:nr])
if nw > 0 {
written += int64(nw)
}
if ew != nil {
err = ew
break
}
if nr != nw {
err = io.ErrShortWrite
break
}
}
if er != nil {
if er != io.EOF {
err = er
}
break
}
}
return written, err
当有一方连接断开时,另一方链接可能不会被正常关闭导致锁一直没有释放。本地连接也一直没有关闭。打开了太多连接也就出现了报错。
修改后的代码:
cryptogram.go
func SecureCopy(src io.ReadWriteCloser, dst io.ReadWriteCloser, secure func(b []byte) error) (written int64, err error) {
defer func() {
if src != nil {
src.Close()
}
if dst != nil {
dst.Close()
}
}()
buf := make([]byte, 1024)
for {
nr, er := src.Read(buf)
if er != nil {
break
}
if nr > 0 {
err = secure(buf)
if err != nil {
return written, err
}
nw, ew := dst.Write(buf[0:nr])
if nw > 0 {
written += int64(nw)
}
if ew != nil {
err = ew
break
}
if nr != nw {
err = io.ErrShortWrite
break
}
}
}
return written, err
}
client.go
把连接的关闭放到copy内部 当一方连接被关闭则关闭两个连接,另一个拷贝就能感知从而读取错误正常关闭并退出。
go SecureCopy(dstServer, localClient, auth.Decrypt)
SecureCopy(localClient, dstServer, auth.Encrypt)