Source File
tcpdialer.go
Belonging Package
github.com/valyala/fasthttp
package fasthttpimport ()// Dial dials the given TCP addr using tcp4.//// This function has the following additional features comparing to net.Dial://// - It reduces load on DNS resolver by caching resolved TCP addressed// for DNSCacheDuration.// - It dials all the resolved TCP addresses in round-robin manner until// connection is established. This may be useful if certain addresses// are temporarily unreachable.// - It returns ErrDialTimeout if connection cannot be established during// DefaultDialTimeout seconds. Use DialTimeout for customizing dial timeout.//// This dialer is intended for custom code wrapping before passing// to Client.Dial or HostClient.Dial.//// For instance, per-host counters and/or limits may be implemented// by such wrappers.//// The addr passed to the function must contain port. Example addr values://// - foobar.baz:443// - foo.bar:80// - aaa.com:8080func ( string) (net.Conn, error) {return defaultDialer.Dial()}// DialTimeout dials the given TCP addr using tcp4 using the given timeout.//// This function has the following additional features comparing to net.Dial://// - It reduces load on DNS resolver by caching resolved TCP addressed// for DNSCacheDuration.// - It dials all the resolved TCP addresses in round-robin manner until// connection is established. This may be useful if certain addresses// are temporarily unreachable.//// This dialer is intended for custom code wrapping before passing// to Client.Dial or HostClient.Dial.//// For instance, per-host counters and/or limits may be implemented// by such wrappers.//// The addr passed to the function must contain port. Example addr values://// - foobar.baz:443// - foo.bar:80// - aaa.com:8080func ( string, time.Duration) (net.Conn, error) {return defaultDialer.DialTimeout(, )}// DialDualStack dials the given TCP addr using both tcp4 and tcp6.//// This function has the following additional features comparing to net.Dial://// - It reduces load on DNS resolver by caching resolved TCP addressed// for DNSCacheDuration.// - It dials all the resolved TCP addresses in round-robin manner until// connection is established. This may be useful if certain addresses// are temporarily unreachable.// - It returns ErrDialTimeout if connection cannot be established during// DefaultDialTimeout seconds. Use DialDualStackTimeout for custom dial// timeout.//// This dialer is intended for custom code wrapping before passing// to Client.Dial or HostClient.Dial.//// For instance, per-host counters and/or limits may be implemented// by such wrappers.//// The addr passed to the function must contain port. Example addr values://// - foobar.baz:443// - foo.bar:80// - aaa.com:8080func ( string) (net.Conn, error) {return defaultDialer.DialDualStack()}// DialDualStackTimeout dials the given TCP addr using both tcp4 and tcp6// using the given timeout.//// This function has the following additional features comparing to net.Dial://// - It reduces load on DNS resolver by caching resolved TCP addressed// for DNSCacheDuration.// - It dials all the resolved TCP addresses in round-robin manner until// connection is established. This may be useful if certain addresses// are temporarily unreachable.//// This dialer is intended for custom code wrapping before passing// to Client.Dial or HostClient.Dial.//// For instance, per-host counters and/or limits may be implemented// by such wrappers.//// The addr passed to the function must contain port. Example addr values://// - foobar.baz:443// - foo.bar:80// - aaa.com:8080func ( string, time.Duration) (net.Conn, error) {return defaultDialer.DialDualStackTimeout(, )}var defaultDialer = &TCPDialer{Concurrency: 1000}// Resolver represents interface of the tcp resolver.type Resolver interface {LookupIPAddr(context.Context, string) (names []net.IPAddr, err error)}// TCPDialer contains options to control a group of Dial calls.type TCPDialer struct {// Concurrency controls the maximum number of concurrent Dials// that can be performed using this object.// Setting this to 0 means unlimited.//// WARNING: This can only be changed before the first Dial.// Changes made after the first Dial will not affect anything.Concurrency int// LocalAddr is the local address to use when dialing an// address.// If nil, a local address is automatically chosen.LocalAddr *net.TCPAddr// This may be used to override DNS resolving policy, like this:// var dialer = &fasthttp.TCPDialer{// Resolver: &net.Resolver{// PreferGo: true,// StrictErrors: false,// Dial: func (ctx context.Context, network, address string) (net.Conn, error) {// d := net.Dialer{}// return d.DialContext(ctx, "udp", "8.8.8.8:53")// },// },// }Resolver Resolver// DNSCacheDuration may be used to override the default DNS cache duration (DefaultDNSCacheDuration)DNSCacheDuration time.DurationtcpAddrsMap sync.MapconcurrencyCh chan struct{}once sync.Once}// Dial dials the given TCP addr using tcp4.//// This function has the following additional features comparing to net.Dial://// - It reduces load on DNS resolver by caching resolved TCP addressed// for DNSCacheDuration.// - It dials all the resolved TCP addresses in round-robin manner until// connection is established. This may be useful if certain addresses// are temporarily unreachable.// - It returns ErrDialTimeout if connection cannot be established during// DefaultDialTimeout seconds. Use DialTimeout for customizing dial timeout.//// This dialer is intended for custom code wrapping before passing// to Client.Dial or HostClient.Dial.//// For instance, per-host counters and/or limits may be implemented// by such wrappers.//// The addr passed to the function must contain port. Example addr values://// - foobar.baz:443// - foo.bar:80// - aaa.com:8080func ( *TCPDialer) ( string) (net.Conn, error) {return .dial(, false, DefaultDialTimeout)}// DialTimeout dials the given TCP addr using tcp4 using the given timeout.//// This function has the following additional features comparing to net.Dial://// - It reduces load on DNS resolver by caching resolved TCP addressed// for DNSCacheDuration.// - It dials all the resolved TCP addresses in round-robin manner until// connection is established. This may be useful if certain addresses// are temporarily unreachable.//// This dialer is intended for custom code wrapping before passing// to Client.Dial or HostClient.Dial.//// For instance, per-host counters and/or limits may be implemented// by such wrappers.//// The addr passed to the function must contain port. Example addr values://// - foobar.baz:443// - foo.bar:80// - aaa.com:8080func ( *TCPDialer) ( string, time.Duration) (net.Conn, error) {return .dial(, false, )}// DialDualStack dials the given TCP addr using both tcp4 and tcp6.//// This function has the following additional features comparing to net.Dial://// - It reduces load on DNS resolver by caching resolved TCP addressed// for DNSCacheDuration.// - It dials all the resolved TCP addresses in round-robin manner until// connection is established. This may be useful if certain addresses// are temporarily unreachable.// - It returns ErrDialTimeout if connection cannot be established during// DefaultDialTimeout seconds. Use DialDualStackTimeout for custom dial// timeout.//// This dialer is intended for custom code wrapping before passing// to Client.Dial or HostClient.Dial.//// For instance, per-host counters and/or limits may be implemented// by such wrappers.//// The addr passed to the function must contain port. Example addr values://// - foobar.baz:443// - foo.bar:80// - aaa.com:8080func ( *TCPDialer) ( string) (net.Conn, error) {return .dial(, true, DefaultDialTimeout)}// DialDualStackTimeout dials the given TCP addr using both tcp4 and tcp6// using the given timeout.//// This function has the following additional features comparing to net.Dial://// - It reduces load on DNS resolver by caching resolved TCP addressed// for DNSCacheDuration.// - It dials all the resolved TCP addresses in round-robin manner until// connection is established. This may be useful if certain addresses// are temporarily unreachable.//// This dialer is intended for custom code wrapping before passing// to Client.Dial or HostClient.Dial.//// For instance, per-host counters and/or limits may be implemented// by such wrappers.//// The addr passed to the function must contain port. Example addr values://// - foobar.baz:443// - foo.bar:80// - aaa.com:8080func ( *TCPDialer) ( string, time.Duration) (net.Conn, error) {return .dial(, true, )}func ( *TCPDialer) ( string, bool, time.Duration) (net.Conn, error) {.once.Do(func() {if .Concurrency > 0 {.concurrencyCh = make(chan struct{}, .Concurrency)}if .DNSCacheDuration == 0 {.DNSCacheDuration = DefaultDNSCacheDuration}go .tcpAddrsClean()}):= time.Now().Add(), , := .getTCPAddrs(, , )if != nil {return nil,}:= "tcp4"if {= "tcp"}var net.Conn:= uint32(len())for > 0 {, = .tryDial(, &[%], , .concurrencyCh)if == nil {return , nil}if == ErrDialTimeout {return nil,}++--}return nil,}func ( *TCPDialer) ( string, *net.TCPAddr, time.Time, chan struct{}) (net.Conn, error) {:= time.Until()if <= 0 {return nil, ErrDialTimeout}if != nil {select {case <- struct{}{}:default::= AcquireTimer():= falseselect {case <- struct{}{}:case <-.C:= true}ReleaseTimer()if {return nil, ErrDialTimeout}}defer func() { <- }()}:= net.Dialer{}if .LocalAddr != nil {.LocalAddr = .LocalAddr}, := context.WithDeadline(context.Background(), )defer (), := .DialContext(, , .String())if != nil && .Err() == context.DeadlineExceeded {return nil, ErrDialTimeout}return ,}// ErrDialTimeout is returned when TCP dialing is timed out.var ErrDialTimeout = errors.New("dialing to the given TCP address timed out")// DefaultDialTimeout is timeout used by Dial and DialDualStack// for establishing TCP connections.const DefaultDialTimeout = 3 * time.Secondtype tcpAddrEntry struct {addrs []net.TCPAddraddrsIdx uint32pending int32resolveTime time.Time}// DefaultDNSCacheDuration is the duration for caching resolved TCP addresses// by Dial* functions.const DefaultDNSCacheDuration = time.Minutefunc ( *TCPDialer) () {:= 2 * .DNSCacheDurationfor {time.Sleep(time.Second):= time.Now().tcpAddrsMap.Range(func(, interface{}) bool {if , := .(*tcpAddrEntry); && .Sub(.resolveTime) > {.tcpAddrsMap.Delete()}return true})}}func ( *TCPDialer) ( string, bool, time.Time) ([]net.TCPAddr, uint32, error) {, := .tcpAddrsMap.Load(), := .(*tcpAddrEntry)if && && != nil && time.Since(.resolveTime) > .DNSCacheDuration {// Only let one goroutine re-resolve at a time.if atomic.SwapInt32(&.pending, 1) == 0 {= nil}}if == nil {, := resolveTCPAddrs(, , .Resolver, )if != nil {, := .tcpAddrsMap.Load(), = .(*tcpAddrEntry)if && && != nil {// Set pending to 0 so another goroutine can retry.atomic.StoreInt32(&.pending, 0)}return nil, 0,}= &tcpAddrEntry{addrs: ,resolveTime: time.Now(),}.tcpAddrsMap.Store(, )}:= atomic.AddUint32(&.addrsIdx, 1)return .addrs, , nil}func resolveTCPAddrs( string, bool, Resolver, time.Time) ([]net.TCPAddr, error) {, , := net.SplitHostPort()if != nil {return nil,}, := strconv.Atoi()if != nil {return nil,}if == nil {= net.DefaultResolver}, := context.WithDeadline(context.Background(), )defer (), := .LookupIPAddr(, )if != nil {return nil,}:= len():= make([]net.TCPAddr, 0, )for := 0; < ; ++ {:= []if ! && .IP.To4() == nil {continue}= append(, net.TCPAddr{IP: .IP,Port: ,Zone: .Zone,})}if len() == 0 {return nil, errNoDNSEntries}return , nil}var errNoDNSEntries = errors.New("couldn't find DNS entries for the given domain. Try using DialDualStack")
![]() |
The pages are generated with Golds v0.6.7. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |