Skip to content

Commit fdfbb40

Browse files
committed
net: add Dialer.KeepAlive option
LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/68380043
1 parent e2fe968 commit fdfbb40

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/pkg/net/dial.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ type Dialer struct {
4444
// destination is a host name that has multiple address family
4545
// DNS records.
4646
DualStack bool
47+
48+
// KeepAlive specifies the keep-alive period for an active
49+
// network connection.
50+
// If zero, keep-alives are not enabled. Network protocols
51+
// that do not support keep-alives ignore this field.
52+
KeepAlive time.Duration
4753
}
4854

4955
// Return either now+Timeout or Deadline, whichever comes first.
@@ -162,9 +168,19 @@ func (d *Dialer) Dial(network, address string) (Conn, error) {
162168
return dialMulti(network, address, d.LocalAddr, ras, deadline)
163169
}
164170
}
165-
return dial(network, ra.toAddr(), dialer, d.deadline())
171+
c, err := dial(network, ra.toAddr(), dialer, d.deadline())
172+
if d.KeepAlive > 0 && err == nil {
173+
if tc, ok := c.(*TCPConn); ok {
174+
tc.SetKeepAlive(true)
175+
tc.SetKeepAlivePeriod(d.KeepAlive)
176+
testHookSetKeepAlive()
177+
}
178+
}
179+
return c, err
166180
}
167181

182+
var testHookSetKeepAlive = func() {} // changed by dial_test.go
183+
168184
// dialMulti attempts to establish connections to each destination of
169185
// the list of addresses. It will return the first established
170186
// connection and close the other connections. Otherwise it returns

src/pkg/net/dial_test.go

+33
Original file line numberDiff line numberDiff line change
@@ -555,3 +555,36 @@ func TestDialDualStackLocalhost(t *testing.T) {
555555
}
556556
}
557557
}
558+
559+
func TestDialerKeepAlive(t *testing.T) {
560+
ln := newLocalListener(t)
561+
defer ln.Close()
562+
defer func() {
563+
testHookSetKeepAlive = func() {}
564+
}()
565+
go func() {
566+
for {
567+
c, err := ln.Accept()
568+
if err != nil {
569+
return
570+
}
571+
c.Close()
572+
}
573+
}()
574+
for _, keepAlive := range []bool{false, true} {
575+
got := false
576+
testHookSetKeepAlive = func() { got = true }
577+
var d Dialer
578+
if keepAlive {
579+
d.KeepAlive = 30 * time.Second
580+
}
581+
c, err := d.Dial("tcp", ln.Addr().String())
582+
if err != nil {
583+
t.Fatal(err)
584+
}
585+
c.Close()
586+
if got != keepAlive {
587+
t.Errorf("Dialer.KeepAlive = %v: SetKeepAlive called = %v, want %v", d.KeepAlive, got, !got)
588+
}
589+
}
590+
}

0 commit comments

Comments
 (0)