Signed-off-by: Simon Eskildsen <sirup@sirupsen.com>
This commit is contained in:
Simon Eskildsen 2015-03-25 03:09:36 +00:00
Родитель b6b8032a17
Коммит 67bd859481
2 изменённых файлов: 64 добавлений и 7 удалений

Просмотреть файл

@ -0,0 +1,27 @@
# listenbuffer
listenbuffer uses the kernel's listening backlog functionality to queue
connections, allowing applications to start listening immediately and handle
connections later. This is signaled by closing the activation channel passed to
the constructor.
The maximum amount of queued connections depends on the configuration of your
kernel (typically called SOMAXXCON) and cannot be configured in Go with the
net package. See `src/net/sock_platform.go` in the Go tree or consult your
kernel's manual.
activator := make(chan struct{})
buffer, err := NewListenBuffer("tcp", "localhost:4000", activator)
if err != nil {
panic(err)
}
// will block until activator has been closed or is sent an event
client, err := buffer.Accept()
Somewhere else in your application once it's been booted:
close(activator)
`buffer.Accept()` will return the first client in the kernel listening queue, or
continue to block until a client connects or an error occurs.

Просмотреть файл

@ -1,13 +1,37 @@
/*
Package to allow go applications to immediately start
listening on a socket, unix, tcp, udp but hold connections
until the application has booted and is ready to accept them
listenbuffer uses the kernel's listening backlog functionality to queue
connections, allowing applications to start listening immediately and handle
connections later. This is signaled by closing the activation channel passed to
the constructor.
The maximum amount of queued connections depends on the configuration of your
kernel (typically called SOMAXXCON) and cannot be configured in Go with the
net package. See `src/net/sock_platform.go` in the Go tree or consult your
kernel's manual.
activator := make(chan struct{})
buffer, err := NewListenBuffer("tcp", "localhost:4000", activator)
if err != nil {
panic(err)
}
// will block until activator has been closed or is sent an event
client, err := buffer.Accept()
Somewhere else in your application once it's been booted:
close(activator)
`buffer.Accept()` will return the first client in the kernel listening queue, or
continue to block until a client connects or an error occurs.
*/
package listenbuffer
import "net"
// NewListenBuffer returns a listener listening on addr with the protocol.
// NewListenBuffer returns a net.Listener listening on addr with the protocol
// passed. The channel passed is used to activate the listenbuffer when the
// caller is ready to accept connections.
func NewListenBuffer(proto, addr string, activate chan struct{}) (net.Listener, error) {
wrapped, err := net.Listen(proto, addr)
if err != nil {
@ -20,20 +44,26 @@ func NewListenBuffer(proto, addr string, activate chan struct{}) (net.Listener,
}, nil
}
// defaultListener is the buffered wrapper around the net.Listener
type defaultListener struct {
wrapped net.Listener // the real listener to wrap
ready bool // is the listner ready to start accpeting connections
activate chan struct{}
wrapped net.Listener // The net.Listener wrapped by listenbuffer
ready bool // Whether the listenbuffer has been activated
activate chan struct{} // Channel to control activation of the listenbuffer
}
// Close closes the wrapped socket.
func (l *defaultListener) Close() error {
return l.wrapped.Close()
}
// Addr returns the listening address of the wrapped socket.
func (l *defaultListener) Addr() net.Addr {
return l.wrapped.Addr()
}
// Accept returns a client connection on the wrapped socket if the listen buffer
// has been activated. To active the listenbuffer the activation channel passed
// to NewListenBuffer must have been closed or sent an event.
func (l *defaultListener) Accept() (net.Conn, error) {
// if the listen has been told it is ready then we can go ahead and
// start returning connections