1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 |
- package protocol
- import (
- "fmt"
- "net"
- "runtime"
- "strings"
- "sync"
- "github.com/nsqio/nsq/internal/lg"
- )
- type TCPHandler interface {
- Handle(net.Conn)
- }
- func TCPServer(listener net.Listener, handler TCPHandler, logf lg.AppLogFunc) error {
- logf(lg.INFO, "TCP: listening on %s", listener.Addr())
- var wg sync.WaitGroup
- for {
- clientConn, err := listener.Accept()
- if err != nil {
- if nerr, ok := err.(net.Error); ok && nerr.Temporary() {
- logf(lg.WARN, "temporary Accept() failure - %s", err)
- runtime.Gosched()
- continue
- }
- // theres no direct way to detect this error because it is not exposed
- if !strings.Contains(err.Error(), "use of closed network connection") {
- return fmt.Errorf("listener.Accept() error - %s", err)
- }
- break
- }
- wg.Add(1)
- go func() {
- handler.Handle(clientConn)
- wg.Done()
- }()
- }
- // wait to return until all handler goroutines complete
- wg.Wait()
- logf(lg.INFO, "TCP: closing %s", listener.Addr())
- return nil
- }
|