func (cl *Client) parseURI() (err error) {
	cl.remoteURL, err = url.ParseRequestURI(cl.Endpoint)
	if err != nil {
		cl = nil
		return err
	}
	serverAddress := cl.remoteURL.Hostname()
	serverPort := cl.remoteURL.Port()
	switch cl.remoteURL.Scheme {
	case schemeWSS, schemeHTTPS:
		if len(serverPort) == 0 {
			serverPort = defTLSPort
		}
		if cl.TLSConfig == nil {
			cl.TLSConfig = &tls.Config{}
		}
	default:
		if len(serverPort) == 0 {
			serverPort = defPort
		}
		cl.TLSConfig = nil
	}
	cl.remoteAddr = serverAddress + ":" + serverPort
	return nil
}
parseURI parse WebSocket connection URI from Endpoint and get the remote
URL (for checking up scheme) and remote address.
By default, if no port is given, it will be set to 80 or 443 for "wss" or
"https" scheme.

On success it will set the remote address that can be used on open().
On fail it will return an error.
package websocket
import (
	"bytes"
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/url"
	"sync"
	"time"
	"unicode/utf8"
	"github.com/shuLhan/share/lib/debug"
	libhttp "github.com/shuLhan/share/lib/http"
)
const (
	_handshakeReqFormat = "GET %s HTTP/1.1\r\n" +
		"Host: %s\r\n" +
		"Upgrade: websocket\r\n" +
		"Connection: Upgrade\r\n" +
		"Sec-Websocket-Key: %s\r\n" +
		"Sec-Websocket-Version: 13\r\n"
	schemeWSS   = "wss"
	schemeHTTPS = "https"
	defTLSPort  = "443"
	defPort     = "80"
)
var (
	ErrConnClosed = fmt.Errorf("websocket: client is not connected")
)
type Client struct {
	sync.Mutex
	conn net.Conn
	Endpoint string
	TLSConfig *tls.Config
	frame  *Frame
	frames *Frames
	HandleBin ClientHandler
	handleClose ClientHandler
	handlePing ClientHandler
	handlePong ClientHandler
	HandleQuit func()
	HandleRsvControl ClientHandler
	HandleText ClientHandler
	Headers http.Header
	PingInterval time.Duration
	remoteURL  *url.URL
	remoteAddr string
	allowRsv1 bool
	allowRsv2 bool
	allowRsv3 bool
	gracefulClose chan bool
}
func (cl *Client) Close() (err error) {
	cl.Lock()
	defer cl.Unlock()
	if cl.conn == nil {
		return
	}
	packet := NewFrameClose(true, StatusNormal, nil)
	cl.gracefulClose = make(chan bool, 1)
	err = cl.send(packet)
	if err != nil {
		return fmt.Errorf("websocket: Close: %w", err)
	}
	timer := time.NewTimer(defaultTimeout)
loop:
	for {
		select {
		case <-timer.C:
			break loop
		case <-cl.gracefulClose:
			timer.Stop()
			break loop
		}
	}
	err = cl.conn.Close()
	if err != nil {
		err = fmt.Errorf("websocket: Close: %w", err)
	}
	cl.conn = nil
	return err
}
func (cl *Client) Connect() (err error) {
	err = cl.init()
	if err != nil {
		return fmt.Errorf("websocket: Connect: " + err.Error())
	}
	if cl.conn != nil {
		cl.Quit()
	}
	err = cl.open()
	if err != nil {
		return fmt.Errorf("websocket: Connect: " + err.Error())
	}
	var rest []byte
	rest, err = cl.handshake()
	if err != nil {
		_ = cl.conn.Close()
		cl.conn = nil
		return fmt.Errorf("websocket: Connect: " + err.Error())
	}
	if len(rest) > 0 {
		isClosing := cl.handleRaw(rest)
		if isClosing {
			return nil
		}
	}
	if cl.PingInterval < defaultPingInterval {
		cl.PingInterval = defaultPingInterval
	}
	go cl.pinger()
	go cl.serve()
	return nil
}
func dummyHandle(cl *Client, frame *Frame) error {
	return nil
}
func (cl *Client) init() (err error) {
	if cl.HandleBin == nil {
		cl.HandleBin = dummyHandle
	}
	if cl.handleClose == nil {
		cl.handleClose = clientOnClose
	}
	if cl.handlePing == nil {
		cl.handlePing = clientOnPing
	}
	if cl.HandleText == nil {
		cl.HandleText = dummyHandle
	}
	err = cl.parseURI()
	if err != nil {
		return err
	}
	if len(cl.Headers) > 0 {
		cl.Headers.Del(_hdrKeyHost)
		cl.Headers.Del(_hdrKeyUpgrade)
		cl.Headers.Del(_hdrKeyOrigin)
		cl.Headers.Del(_hdrKeyWSKey)
		cl.Headers.Del(_hdrKeyWSVersion)
	}
	return nil
}