func (d *UDP) Send(r *Response) error {
	return d.RespHandler.Write(r, d.writer)
}
Send will deliver the response back to the client.
package udp
import (
	"errors"
	"io"
	"net"
	"strconv"
	"sync"
	"sync/atomic"
	"time"
)
var (
	ErrInvalidConfiguration = errors.New("Invalid Configuration")
	ErrInvalidNetType       = errors.New("Invalid NetType Configuration")
	ErrInvalidConnHandler   = errors.New("Invalid Connection Handler Configuration")
	ErrInvalidReqHandler    = errors.New("Invalid Request Handler Configuration")
	ErrInvalidRespHandler   = errors.New("Invalid Response Handler Configuration")
)
type temporary interface {
	Temporary() bool
}
type UDP struct {
	Config
	Name string
	ipAddress string
	port      int
	udpAddr   *net.UDPAddr
	listener   *net.UDPConn
	listenerMu sync.RWMutex
	reader io.Reader
	writer io.Writer
	wg           sync.WaitGroup
	shuttingDown int32
}
func New(name string, cfg Config) (*UDP, error) {
	if err := cfg.Validate(); err != nil {
		return nil, err
	}
	udpAddr, err := net.ResolveUDPAddr(cfg.NetType, cfg.Addr)
	if err != nil {
		return nil, err
	}
	udp := UDP{
		Config: cfg,
		Name:   name,
		ipAddress: udpAddr.IP.String(),
		port:      udpAddr.Port,
		udpAddr:   udpAddr,
	}
	return &udp, nil
}
func join(ip string, port int) string {
	return net.JoinHostPort(ip, strconv.Itoa(port))
}
func (d *UDP) Start() error {
	d.listenerMu.Lock()
	{
		if d.listener != nil {
			d.listenerMu.Unlock()
			return errors.New("this UDP has already been started")
		}
	}
	d.listenerMu.Unlock()
	var waitStart sync.WaitGroup
	waitStart.Add(1)
	d.wg.Add(1)
	go func() {
		for {
			d.listenerMu.Lock()
			{
				if d.listener == nil {
					var err error
					d.listener, err = net.ListenUDP(d.NetType, d.udpAddr)
					if err != nil {
						panic(err)
					}
					d.reader, d.writer = d.ConnHandler.Bind(d.listener)
					waitStart.Done()
					d.Event("accept", "Waiting For Data : IPAddress[ %s ]", join(d.ipAddress, d.port))
				}
			}
			d.listenerMu.Unlock()
			udpAddr, data, length, err := d.ReqHandler.Read(d.reader)
			timeRead := time.Now()
			if err != nil {
				if atomic.LoadInt32(&d.shuttingDown) == 1 {
					d.listenerMu.Lock()
					{
						d.listener = nil
					}
					d.listenerMu.Unlock()
					break
				}
				d.Event("accept", "ERROR : %v", err)
				if e, ok := err.(temporary); ok && !e.Temporary() {
					d.listenerMu.Lock()
					{
						d.listener.Close()
						d.listener = nil
					}
					d.listenerMu.Unlock()
					waitStart.Add(1)
				}
				continue
			}
			isIPv6 := true
			if ip4 := udpAddr.IP.To4(); ip4 != nil {
				udpAddr.IP = ip4
				isIPv6 = false
			}
			req := Request{
				UDP:     d,
				UDPAddr: udpAddr,
				IsIPv6:  isIPv6,
				ReadAt:  timeRead,
				Data:    data,
				Length:  length,
			}
			d.ReqHandler.Process(&req)
		}
		d.wg.Done()
		d.Event("accept", "Shutdown : IPAddress[ %s ]", join(d.ipAddress, d.port))
		return
	}()
	waitStart.Wait()
	return nil
}
func (d *UDP) Stop() error {
	d.listenerMu.Lock()
	{
		if d.listener == nil {
			d.listenerMu.Unlock()
			return errors.New("this UDP has already been stopped")
		}
	}
	d.listenerMu.Unlock()
	atomic.StoreInt32(&d.shuttingDown, 1)
	d.listenerMu.Lock()
	{
		d.listener.Close()
	}
	d.listenerMu.Unlock()
	d.wg.Wait()
	return nil
}