Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
100 lines (88 sloc) 1.85 KB
package tcpserver
import (
"context"
"log"
"net"
"sync"
)
//ConnectionHandler connection handler definition
type ConnectionHandler func(ctx context.Context, conn net.Conn) error
//Server represent tcpserver
type Server struct {
network string
address string
handler ConnectionHandler
listener net.Listener
wgroup sync.WaitGroup
}
//Network option for listener
func Network(inet string) ServerOpt {
return func(srv *Server) {
if len(inet) != 0 {
srv.network = inet
}
}
}
//Address option for listener
func Address(addr string) ServerOpt {
return func(srv *Server) {
if len(addr) != 0 {
srv.address = addr
}
}
}
//Handler option for connection
func Handler(h ConnectionHandler) ServerOpt {
return func(srv *Server) {
if h != nil {
srv.handler = h
}
}
}
//ServerOpt typedef
type ServerOpt func(*Server)
//NewServer create a new tcpserver
func NewServer(opts ...ServerOpt) *Server {
serv := &Server{}
for _, opt := range opts {
opt(serv)
}
return serv
}
//Serve tcpserver serving
func (srv *Server) Serve(ctx context.Context) error {
ln, err := net.Listen(srv.network, srv.address)
if err != nil {
return err
}
log.Println("tcpserver serving at ", srv.network, srv.address)
srv.listener = ln
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
con, err := srv.listener.Accept()
if err != nil {
if ne, ok := err.(net.Error); ok && ne.Temporary() {
log.Printf("warning: accept temp err: %v", ne)
continue
}
log.Println(err)
return err
}
srv.wgroup.Add(1)
go func() {
defer srv.wgroup.Done()
if err := srv.handler(ctx, con); err != nil {
log.Printf("connection %s handle failed: %s\n", con.RemoteAddr().String(), err)
}
}()
}
}
}
//Close tcpserver waiting all connections finished
func (srv *Server) Close() {
_ = srv.listener.Close()
srv.wgroup.Wait()
}
You can’t perform that action at this time.