func (c *Client) Send(packet Packet) error {
	addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", c.ip, c.port))
	if err != nil {
		return err
	}
	conn, err := net.DialUDP("udp", c.laddr, addr)
	if err != nil {
		return err
	}
	defer conn.Close()
	data, err := packet.MarshalBinary()
	if err != nil {
		return err
	}
	if _, err = conn.Write(data); err != nil {
		return err
	}
	return nil
}
Send sends an OSC Bundle or an OSC Message.
package osc
import (
	"bufio"
	"bytes"
	"encoding"
	"encoding/binary"
	"errors"
	"fmt"
	"net"
	"reflect"
	"regexp"
	"strings"
	"time"
)
const (
	secondsFrom1900To1970 = 2208988800
	bundleTagString       = "#bundle"
)
type Packet interface {
	encoding.BinaryMarshaler
}
type Message struct {
	Address   string
	Arguments []interface{}
}
var _ Packet = (*Message)(nil)
type Bundle struct {
	Timetag  Timetag
	Messages []*Message
	Bundles  []*Bundle
}
var _ Packet = (*Bundle)(nil)
type Client struct {
	ip    string
	port  int
	laddr *net.UDPAddr
}
type Server struct {
	Addr        string
	Dispatcher  Dispatcher
	ReadTimeout time.Duration
	close       func() error
}
type Timetag struct {
	timeTag  uint64  
	time     time.Time
	MinValue uint64  
}
type Dispatcher interface {
	Dispatch(packet Packet)
}
type Handler interface {
	HandleMessage(msg *Message)
}
type HandlerFunc func(msg *Message)
func (f HandlerFunc) HandleMessage(msg *Message) {
	f(msg)
}
type StandardDispatcher struct {
	handlers       map[string]Handler
	defaultHandler Handler
}
func NewStandardDispatcher() *StandardDispatcher {
	return &StandardDispatcher{handlers: make(map[string]Handler)}
}
func (s *StandardDispatcher) AddMsgHandler(addr string, handler HandlerFunc) error {
	if addr == "*" {
		s.defaultHandler = handler
		return nil
	}
	for _, chr := range "*?,[]{}# " {
		if strings.Contains(addr, fmt.Sprintf("%c", chr)) {
			return errors.New("OSC Address string may not contain any characters in \"*?,[]{}#")
		}
	}
	if addressExists(addr, s.handlers) {
		return errors.New("OSC address exists already")
	}
	s.handlers[addr] = handler
	return nil
}
func (s *StandardDispatcher) Dispatch(packet Packet) {
	switch p := packet.(type) {
	default:
		return
	case *Message:
		for addr, handler := range s.handlers {
			if p.Match(addr) {
				handler.HandleMessage(p)
			}
		}
		if s.defaultHandler != nil {
			s.defaultHandler.HandleMessage(p)
		}
	case *Bundle:
		timer := time.NewTimer(p.Timetag.ExpiresIn())
		go func() {
			<-timer.C
			for _, message := range p.Messages {
				for address, handler := range s.handlers {
					if message.Match(address) {
						handler.HandleMessage(message)
					}
				}
				if s.defaultHandler != nil {
					s.defaultHandler.HandleMessage(message)
				}
			}
			for _, b := range p.Bundles {
				s.Dispatch(b)
			}
		}()
	}
}
func NewMessage(addr string, args ...interface{}) *Message {
	return &Message{Address: addr, Arguments: args}
}
func (msg *Message) Append(args ...interface{}) {
	msg.Arguments = append(msg.Arguments, args...)
}
func (msg *Message) Equals(m *Message) bool {
	return reflect.DeepEqual(msg, m)
}
func (msg *Message) Clear() {
	msg.Address = ""
	msg.ClearData()
}
func (msg *Message) ClearData() {
	msg.Arguments = msg.Arguments[len(msg.Arguments):]
}
func (msg *Message) Match(addr string) bool {
	exp := getRegEx(msg.Address)
	if exp.MatchString(addr) {
		return true
	}
	return false
}
func (msg *Message) TypeTags() (string, error) {
	if msg == nil {
		return "", fmt.Errorf("message is nil")
	}
	tags := ","
	for _, m := range msg.Arguments {
		s, err := getTypeTag(m)
		if err != nil {
			return "", err
		}
		tags += s
	}
	return tags, nil
}
func (msg *Message) String() string {
	if msg == nil {
		return ""
	}
	tags, err := msg.TypeTags()
	if err != nil {
		return ""
	}
	formatString := "%s %s"
	var args []interface{}
	args = append(args, msg.Address)
	args = append(args, tags)
	for _, arg := range msg.Arguments {
		switch arg.(type) {
		case bool, int32, int64, float32, float64, string:
			formatString += " %v"
			args = append(args, arg)
		case nil:
			formatString += " %s"
			args = append(args, "Nil")
		case []byte:
			formatString += " %s"
			args = append(args, "blob")
		case Timetag:
			formatString += " %d"
			timeTag := arg.(Timetag)
			args = append(args, timeTag.TimeTag())
		}
	}
	return fmt.Sprintf(formatString, args...)
}
func (msg *Message) CountArguments() int {
	return len(msg.Arguments)
}
func (msg *Message) MarshalBinary() ([]byte, error) {
	data := new(bytes.Buffer)
	if _, err := writePaddedString(msg.Address, data); err != nil {
		return nil, err
	}
	typetags := []byte{','}
	payload := new(bytes.Buffer)
	for _, arg := range msg.Arguments {
		switch t := arg.(type) {
		default:
			return nil, fmt.Errorf("OSC - unsupported type: %T", t)
		case bool:
			if arg.(bool) == true {
				typetags = append(typetags, 'T')
			} else {
				typetags = append(typetags, 'F')
			}
		case nil:
			typetags = append(typetags, 'N')
		case int32:
			typetags = append(typetags, 'i')
			if err := binary.Write(payload, binary.BigEndian, int32(t)); err != nil {
				return nil, err
			}
		case float32:
			typetags = append(typetags, 'f')
			if err := binary.Write(payload, binary.BigEndian, float32(t)); err != nil {
				return nil, err
			}
		case string:
			typetags = append(typetags, 's')
			if _, err := writePaddedString(t, payload); err != nil {
				return nil, err
			}
		case []byte:
			typetags = append(typetags, 'b')
			if _, err := writeBlob(t, payload); err != nil {
				return nil, err
			}
		case int64:
			typetags = append(typetags, 'h')
			if err := binary.Write(payload, binary.BigEndian, int64(t)); err != nil {
				return nil, err
			}
		case float64:
			typetags = append(typetags, 'd')
			if err := binary.Write(payload, binary.BigEndian, float64(t)); err != nil {
				return nil, err
			}
		case Timetag:
			typetags = append(typetags, 't')
			timeTag := arg.(Timetag)
			b, err := timeTag.MarshalBinary()
			if err != nil {
				return nil, err
			}
			if _, err = payload.Write(b); err != nil {
				return nil, err
			}
		}
	}
	if _, err := writePaddedString(string(typetags), data); err != nil {
		return nil, err
	}
	if _, err := data.Write(payload.Bytes()); err != nil {
		return nil, err
	}
	return data.Bytes(), nil
}
func NewBundle(time time.Time) *Bundle {
	return &Bundle{Timetag: *NewTimetag(time)}
}
func (b *Bundle) Append(pck Packet) error {
	switch t := pck.(type) {
	default:
		return fmt.Errorf("unsupported OSC packet type: only Bundle and Message are supported")
	case *Bundle:
		b.Bundles = append(b.Bundles, t)
	case *Message:
		b.Messages = append(b.Messages, t)
	}
	return nil
}
func (b *Bundle) MarshalBinary() ([]byte, error) {
	data := new(bytes.Buffer)
	if _, err := writePaddedString("#bundle", data); err != nil {
		return nil, err
	}
	bd, err := b.Timetag.MarshalBinary()
	if err != nil {
		return nil, err
	}
	if _, err = data.Write(bd); err != nil {
		return nil, err
	}
	for _, m := range b.Messages {
		buf, err := m.MarshalBinary()
		if err != nil {
			return nil, err
		}
		if err = binary.Write(data, binary.BigEndian, int32(len(buf))); err != nil {
			return nil, err
		}
		if _, err = data.Write(buf); err != nil {
			return nil, err
		}
	}
	for _, b := range b.Bundles {
		buf, err := b.MarshalBinary()
		if err != nil {
			return nil, err
		}
		if err = binary.Write(data, binary.BigEndian, int32(len(buf))); err != nil {
			return nil, err
		}
		_, err = data.Write(buf)
		if err != nil {
			return nil, err
		}
	}
	return data.Bytes(), nil
}
func NewClient(ip string, port int) *Client {
	return &Client{ip: ip, port: port, laddr: nil}
}
func (c *Client) IP() string { return c.ip }
func (c *Client) SetIP(ip string) { c.ip = ip }
func (c *Client) Port() int { return c.port }
func (c *Client) SetPort(port int) { c.port = port }
func (c *Client) SetLocalAddr(ip string, port int) error {
	laddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", ip, port))
	if err != nil {
		return err
	}
	c.laddr = laddr
	return nil
}