Skip to content

Instantly share code, notes, and snippets.

@jbardin
Last active September 8, 2023 19:04
Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save jbardin/9663312 to your computer and use it in GitHub Desktop.
Save jbardin/9663312 to your computer and use it in GitHub Desktop.
package nettimeout
import (
"net"
"time"
)
// Listener wraps a net.Listener, and gives a place to store the timeout
// parameters. On Accept, it will wrap the net.Conn with our own Conn for us.
type Listener struct {
net.Listener
ReadTimeout time.Duration
WriteTimeout time.Duration
}
func (l *Listener) Accept() (net.Conn, error) {
c, err := l.Listener.Accept()
if err != nil {
return nil, err
}
tc := &Conn{
Conn: c,
ReadTimeout: l.ReadTimeout,
WriteTimeout: l.WriteTimeout,
}
return tc, nil
}
// Conn wraps a net.Conn, and sets a deadline for every read
// and write operation.
type Conn struct {
net.Conn
ReadTimeout time.Duration
WriteTimeout time.Duration
}
func (c *Conn) Read(b []byte) (int, error) {
err := c.Conn.SetReadDeadline(time.Now().Add(c.ReadTimeout))
if err != nil {
return 0, err
}
return c.Conn.Read(b)
}
func (c *Conn) Write(b []byte) (int, error) {
err := c.Conn.SetWriteDeadline(time.Now().Add(c.WriteTimeout))
if err != nil {
return 0, err
}
return c.Conn.Write(b)
}
func NewListener(addr string, readTimeout, writeTimeout time.Duration) (net.Listener, error) {
l, err := net.Listen("tcp", addr)
if err != nil {
return nil, err
}
tl := &Listener{
Listener: l,
ReadTimeout: readTimeout,
WriteTimeout: writeTimeout,
}
return tl, nil
}
@tve
Copy link

tve commented Aug 15, 2014

Thanks for this gist, gives me a starting point to adapt from! One thing you may want to consider is actively closing the connection when a timeout occurs. In particular the errors on writes pretty much get swept under the rug by the net/http code and you end up with a dead socket that stays open. If you're interested this thread has some more info: https://groups.google.com/forum/#!topic/golang-nuts/oBIh_R7-pJQ

@jbardin
Copy link
Author

jbardin commented Aug 18, 2014

@tve - Oh, I know -- I filed that issue 😄 (I don't know where notifications to these gists go, but I just happened upon this comment)

I don't think you want to Close the conn every time. If the connection needs to be closed, and the code handling the connection doesn't do it, that's a bug.

Also, you may not want the connection closed, so that it can shutdown half the connection for various reasons (I have some lower-level network code that needs to do this).

@lumieru
Copy link

lumieru commented Jul 9, 2015

If the size of data to read or write is very large but the network speed is very slow, then the total time needed to read/write may be larger than ReadTimeout/WriteTimeout and cause a timeout error. Will this situation still occur when the above code is used?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment