func (c *TCPClient) execRequest(message *proto.Msg) (*proto.Msg, error) {
	err := c.conn.SetDeadline(time.Now().Add(c.timeout))
	if err != nil {
		return nil, err
	}
	msg := &proto.Msg{}
	data, err := pb.Marshal(message)
	if err != nil {
		return msg, err
	}
	b := new(bytes.Buffer)
	if err = binary.Write(b, binary.BigEndian, uint32(len(data))); err != nil {
		return msg, err
	}
	if _, err = c.conn.Write(b.Bytes()); err != nil {
		return msg, err
	}
	if _, err = c.conn.Write(data); err != nil {
		return msg, err
	}
	var header uint32
	if err = binary.Read(c.conn, binary.BigEndian, &header); err != nil {
		return msg, err
	}
	response := make([]byte, header)
	if err = readMessages(c.conn, response); err != nil {
		return msg, err
	}
	if err = pb.Unmarshal(response, msg); err != nil {
		return msg, err
	}
	return msg, nil
}
execRequest will send a TCP message to Riemann
package riemanngo
import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/binary"
	"io"
	"io/ioutil"
	"net"
	"time"
	pb "github.com/golang/protobuf/proto"
	"github.com/riemann/riemann-go-client/proto"
	"gopkg.in/tomb.v2"
)
type TCPClient struct {
	tls          bool
	addr         string
	conn         net.Conn
	requestQueue chan request
	timeout      time.Duration
	tlsConfig    *tls.Config
	t            tomb.Tomb
}
func NewTLSClient(addr string, tlsConfig *tls.Config, timeout time.Duration) (*TCPClient, error) {
	t := &TCPClient{
		tls:          true,
		addr:         addr,
		tlsConfig:    tlsConfig,
		requestQueue: make(chan request),
		timeout:      timeout,
	}
	return t, nil
}
func GetTLSConfig(serverName string, certPath string, keyPath string, insecure bool) (*tls.Config, error) {
	certFile, err := ioutil.ReadFile(certPath)
	if err != nil {
		return nil, err
	}
	cert, err := tls.LoadX509KeyPair(certPath, keyPath)
	if err != nil {
		return nil, err
	}
	clientCertPool := x509.NewCertPool()
	clientCertPool.AppendCertsFromPEM(certFile)
	config := tls.Config{
		Certificates:       []tls.Certificate{cert},
		RootCAs:            clientCertPool,
		InsecureSkipVerify: insecure}
	if !insecure {
		config.ServerName = serverName
	}
	return &config, nil
}
func NewTCPClient(addr string, timeout time.Duration) *TCPClient {
	t := &TCPClient{
		tls:          false,
		addr:         addr,
		requestQueue: make(chan request),
		timeout:      timeout,
	}
	return t
}
func (c *TCPClient) Connect() error {
	c.t.Go(func() error {
		return c.runRequestQueue()
	})
	connection, err := net.DialTimeout("tcp", c.addr, c.timeout)
	if err != nil {
		return err
	}
	if c.tls {
		tlsConn := tls.Client(connection, c.tlsConfig)
		err = tlsConn.Handshake()
		if err != nil {
			return err
		}
		c.conn = tlsConn
	} else {
		c.conn = connection
	}
	return nil
}
func (c *TCPClient) Close() error {
	c.t.Kill(nil)
	_ = c.t.Wait()
	close(c.requestQueue)
	err := c.conn.Close()
	return err
}
func (c *TCPClient) Send(message *proto.Msg) (*proto.Msg, error) {
	responseCh := make(chan response)
	c.requestQueue <- request{message, responseCh}
	r := <-responseCh
	return r.message, r.err
}
func (c *TCPClient) runRequestQueue() error {
	for {
		select {
		case <-c.t.Dying():
			return nil
		case req := <-c.requestQueue:
			message := req.message
			responseCh := req.responseCh
			msg, err := c.execRequest(message)
			responseCh <- response{msg, err}
		}
	}
}