This repository has been archived on 2026-01-07. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Game/Server/robot/internal/ws/client.go

127 lines
2.4 KiB
Go

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)
}
}