package ws import ( "common/log" "common/proto/sc/sc_pb" "context" "crypto/tls" "errors" "fmt" "github.com/gorilla/websocket" "google.golang.org/protobuf/proto" ) type Client struct { addr string token string conn *websocket.Conn ctx context.Context cancel context.CancelFunc writeChaen chan []byte } func NewClient(addr string, token string) *Client { c := &Client{ addr: addr, token: token, writeChaen: make(chan []byte, 1024), } c.ctx, c.cancel = context.WithCancel(context.Background()) return c } func (c *Client) Start() { go func() { dialer := websocket.DefaultDialer dialer.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} conn, _, err := dialer.Dial(fmt.Sprintf("%v?token=%v", c.addr, c.token), nil) if err != nil { log.Errorf("connect error %v", err.Error()) return } c.conn = conn _ = c.WriteMessage(sc_pb.MessageID_MESSAGE_ID_ENTER_INSTANCE, &sc_pb.C2S_EnterInstance{ InstanceID: 1, }) go c.startReader() go c.startWriter() select { case <-c.ctx.Done(): c.onStop() return } }() } func (c *Client) startReader() { for { select { case <-c.ctx.Done(): return default: _, msgByte, err := c.conn.ReadMessage() if err != nil { log.Errorf("read error quit %s", err) c.Stop() return } msg := &sc_pb.Message{} if err = proto.Unmarshal(msgByte, msg); err != nil { continue } if r, ok := router[msg.ID]; ok { r.Handle(msg.Payload, c) } } } } func (c *Client) startWriter() { for { select { case data, ok := <-c.writeChaen: if ok { if err := c.conn.WriteMessage(websocket.BinaryMessage, data); err != nil { log.Errorf("Send Buff Data error:, %s Conn Writer exit", err) return } } else { log.Errorf("msgBuffChan is Closed") } case <-c.ctx.Done(): return } } } // WriteMessage 发送消息给服务器 func (c *Client) WriteMessage(msgID sc_pb.MessageID, data proto.Message) error { d, err := proto.Marshal(data) if err != nil { return err } p := &sc_pb.Message{ ID: msgID, Payload: d, } marshal, _ := proto.Marshal(p) select { case c.writeChaen <- marshal: default: return errors.New("send buff chan is full") } return nil } func (c *Client) Stop() { c.cancel() } func (c *Client) onStop() { if err := c.conn.Close(); err != nil { log.Errorf("close client error %v", err) } }