func (s *Socket) Read(timeout ...time.Duration) (string, error) {
	return s.mainChannel.Read(timeout...)
}
Read the next message from the socket. This method is blocking.
One variadic argument sets a timeout duration.
If no timeout is specified, this method will block forever.
ErrSocketClosed is returned, if the socket connection is closed.
ErrReadTimeout is returned, if the timeout is reached.
package glue
import (
	"encoding/json"
	"errors"
	"fmt"
	"runtime/debug"
	"sync"
	"time"
	"github.com/Sirupsen/logrus"
	"github.com/blang/semver"
	"github.com/desertbit/glue/backend"
	"github.com/desertbit/glue/log"
	"github.com/desertbit/glue/utils"
)
const (
	Version = "1.8.0"
)
const (
	socketIDLength = 20
	pingPeriod = 30 * time.Second
	pingResponseTimeout = 7 * time.Second
	mainChannelName = "m"
	cmdLen               = 2
	cmdInit              = "in"
	cmdPing              = "pi"
	cmdPong              = "po"
	cmdClose             = "cl"
	cmdInvalid           = "iv"
	cmdDontAutoReconnect = "dr"
	cmdChannelData       = "cd"
)
var (
	ErrSocketClosed = errors.New("the socket connection is closed")
	ErrReadTimeout  = errors.New("the read timeout was reached")
)
var (
	serverVersion semver.Version
)
type ClosedChan <-chan struct{}
type OnCloseFunc func()
type OnReadFunc func(data string)
type initData struct {
	SocketID string `json:"socketID"`
}
type clientInitData struct {
	Version string `json:"version"`
}
type Socket struct {
	Value interface{}
	server *Server
	bs     backend.BackendSocket
	id            string  
	isInitialized bool
	channels    *channels
	mainChannel *Channel
	writeChan    chan string
	readChan     chan string
	isClosedChan chan struct{}
	onCloseFunc OnCloseFunc
	pingTimer         *time.Timer
	pingTimeout       *time.Timer
	sendPingMutex     sync.Mutex
	pingRequestActive bool
}
func newSocket(server *Server, bs backend.BackendSocket) *Socket {
	s := &Socket{
		server: server,
		bs:     bs,
		id:       utils.RandomString(socketIDLength),
		channels: newChannels(),
		writeChan:    bs.WriteChan(),
		readChan:     bs.ReadChan(),
		isClosedChan: make(chan struct{}),
		pingTimer:   time.NewTimer(pingPeriod),
		pingTimeout: time.NewTimer(pingResponseTimeout),
	}
	s.mainChannel = s.Channel(mainChannelName)
	bs.OnClose(s.onClose)
	s.pingTimeout.Stop()
	func() {
		s.server.socketsMutex.Lock()
		defer s.server.socketsMutex.Unlock()
		for {
			if _, ok := s.server.sockets[s.id]; !ok {
				break
			}
			s.id = utils.RandomString(socketIDLength)
		}
		s.server.sockets[s.id] = s
	}()
	go s.pingTimeoutHandler()
	go s.readLoop()
	go s.pingLoop()
	return s
}
func (s *Socket) ID() string {
	return s.id
}
func (s *Socket) IsInitialized() bool {
	return s.isInitialized
}
func (s *Socket) RemoteAddr() string {
	return s.bs.RemoteAddr()
}
func (s *Socket) UserAgent() string {
	return s.bs.UserAgent()
}
func (s *Socket) Close() {
	s.bs.Close()
}
func (s *Socket) IsClosed() bool {
	return s.bs.IsClosed()
}
func (s *Socket) OnClose(f OnCloseFunc) {
	s.onCloseFunc = f
}
func (s *Socket) ClosedChan() ClosedChan {
	return s.isClosedChan
}
func (s *Socket) Write(data string) {
	s.mainChannel.Write(data)
}