[GH-ISSUE #151] 关于proxy何时Close上下游连接的讨论 #84

Closed
opened 2026-02-27 23:15:22 +03:00 by kerem · 0 comments
Owner

Originally created by @ansoda on GitHub (Sep 28, 2018).
Original GitHub issue: https://github.com/snail007/goproxy/issues/151

type NetReadWriteCloser interface {
	io.ReadWriteCloser
	CloseRead() error
	CloseWrite() error
}
func ioBind(dst NetReadWriteCloser, src NetReadWriteCloser, fn func(err interface{}), log *logger.Logger, close bool) {
	go func() {
		defer func() {
			if err := recover(); err != nil {
				log.Printf("bind crashed %s", err)
			}
		}()

		var e1 error
		var e2 error

		wg := sync.WaitGroup{}
		wg.Add(2)

		go func() {
			defer func() {
				if err := recover(); err != nil {
					log.Printf("bind crashed %s", err)
				}
			}()
			defer wg.Done()

			e1 = ioCopy(dst, src)
			dst.CloseWrite()
		}()
		go func() {
			defer func() {
				if err := recover(); err != nil {
					log.Printf("bind crashed %s", err)
				}
			}()
			defer wg.Done()

			e2 = ioCopy(src, dst)
			src.CloseWrite()
		}()

		wg.Wait()

		func() {
			defer func() {
				_ = recover()
			}()
			if close {
				src.Close()
			}
		}()
		func() {
			defer func() {
				_ = recover()
			}()
			if close {
				dst.Close()
			}
		}()
		if fn != nil {
			var err error
			if e1 != nil {
				err = e1
			} else if e2 != nil {
				err = e2
			}

			fn(err)
		}
	}()
}

作为代理程序,上面给个参考改进讨论,不管是上下游的哪一方先主动中断连接,proxy都不应该主动的close掉与另外一方的连接。 IoBind这个函数中,proxy是不是应该先调用dst.CloseWrite(),等两方都主动断开连接后,proxy再调用两方的Close()。
这样既可以避免上下游一方先只关闭写通道但没有关闭读通道时造成数据读取不完整的问题,同时也可以减少服务器的time_wait过多的问题。

Originally created by @ansoda on GitHub (Sep 28, 2018). Original GitHub issue: https://github.com/snail007/goproxy/issues/151 type NetReadWriteCloser interface { io.ReadWriteCloser CloseRead() error CloseWrite() error } func ioBind(dst NetReadWriteCloser, src NetReadWriteCloser, fn func(err interface{}), log *logger.Logger, close bool) { go func() { defer func() { if err := recover(); err != nil { log.Printf("bind crashed %s", err) } }() var e1 error var e2 error wg := sync.WaitGroup{} wg.Add(2) go func() { defer func() { if err := recover(); err != nil { log.Printf("bind crashed %s", err) } }() defer wg.Done() e1 = ioCopy(dst, src) dst.CloseWrite() }() go func() { defer func() { if err := recover(); err != nil { log.Printf("bind crashed %s", err) } }() defer wg.Done() e2 = ioCopy(src, dst) src.CloseWrite() }() wg.Wait() func() { defer func() { _ = recover() }() if close { src.Close() } }() func() { defer func() { _ = recover() }() if close { dst.Close() } }() if fn != nil { var err error if e1 != nil { err = e1 } else if e2 != nil { err = e2 } fn(err) } }() } 作为代理程序,上面给个参考改进讨论,不管是上下游的哪一方先主动中断连接,proxy都不应该主动的close掉与另外一方的连接。 IoBind这个函数中,proxy是不是应该先调用dst.CloseWrite(),等两方都主动断开连接后,proxy再调用两方的Close()。 这样既可以避免上下游一方先只关闭写通道但没有关闭读通道时造成数据读取不完整的问题,同时也可以减少服务器的time_wait过多的问题。
kerem closed this issue 2026-02-27 23:15:22 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/goproxy#84
No description provided.