修复一个open too many files

作者:
淡白
创建时间:
Sep 9, 2021, 6:00:03 PM
Go socket 34

摘要:在使用socks5代理客户端发现,很多连接没有被正常关闭。在文件client.go中当代理类型不为http时会执行以下代码// 和远程端建立安全信道wg := new(sync.WaitGroup)wg.Add(2)// 本地的内容copy到远程端go func() {defer wg.Done()

在使用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)
服务提供商:提速啦