|
@@ -6,7 +6,6 @@ import (
|
|
|
"fmt"
|
|
"fmt"
|
|
|
"mtp20access/global"
|
|
"mtp20access/global"
|
|
|
rsp "mtp20access/model/mq/response"
|
|
rsp "mtp20access/model/mq/response"
|
|
|
- "mtp20access/model/quote/request"
|
|
|
|
|
"mtp20access/packet"
|
|
"mtp20access/packet"
|
|
|
"mtp20access/publish"
|
|
"mtp20access/publish"
|
|
|
"sync"
|
|
"sync"
|
|
@@ -27,12 +26,6 @@ type Client struct {
|
|
|
curSerialNumber uint32 // 当前业务流水号
|
|
curSerialNumber uint32 // 当前业务流水号
|
|
|
asyncTasks map[string]*AsyncTask // key:SessionId_FuncodeRsp_SerialNumber
|
|
asyncTasks map[string]*AsyncTask // key:SessionId_FuncodeRsp_SerialNumber
|
|
|
|
|
|
|
|
- wsQuoteConn *websocket.Conn // 终端行情WebSocket连接
|
|
|
|
|
- quoteWriteChan chan []byte // 推送队列 Access -> Client
|
|
|
|
|
- quoteChan chan interface{} // 接收实时行情订阅channel QuoteServer -> Access
|
|
|
|
|
- quoteSubs []request.QuoteGoods // 当前已订阅行情的商品
|
|
|
|
|
- // wsQuoteCloseChan chan struct{} // 终端WebSocket连接关闭信号
|
|
|
|
|
-
|
|
|
|
|
wsTradeConn *websocket.Conn // 终端交易WebSocket连接
|
|
wsTradeConn *websocket.Conn // 终端交易WebSocket连接
|
|
|
tradeWriteChan chan []byte // 推送队列 Access -> Client
|
|
tradeWriteChan chan []byte // 推送队列 Access -> Client
|
|
|
tradeChan chan interface{} // 接收交易通知channel RabbitMQ -> Access
|
|
tradeChan chan interface{} // 接收交易通知channel RabbitMQ -> Access
|
|
@@ -50,33 +43,6 @@ func (r *Client) GetSerialNumber() uint32 {
|
|
|
return r.curSerialNumber
|
|
return r.curSerialNumber
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// SetQuoteSubs 设置商品行情订阅信息
|
|
|
|
|
-func (r *Client) SetQuoteSubs(req request.QuoteSubscribeReq) {
|
|
|
|
|
- // r.qmtx.Lock()
|
|
|
|
|
- // defer r.qmtx.Unlock()
|
|
|
|
|
-
|
|
|
|
|
- r.quoteSubs = req.QuoteGoodses
|
|
|
|
|
-
|
|
|
|
|
- // 从订阅中心订阅行情通知
|
|
|
|
|
- if r.quoteChan != nil {
|
|
|
|
|
- global.M2A_Publish.Unsubscribe(publish.Topic_Quote, r.quoteChan)
|
|
|
|
|
- }
|
|
|
|
|
- r.quoteChan = global.M2A_Publish.Subscribe(publish.Topic_Quote)
|
|
|
|
|
-
|
|
|
|
|
- go func() {
|
|
|
|
|
- for {
|
|
|
|
|
- msg, ok := <-r.quoteChan
|
|
|
|
|
- if !ok {
|
|
|
|
|
- return // 管道已关闭,退出循环
|
|
|
|
|
- }
|
|
|
|
|
- // 向客户端发送行情信息
|
|
|
|
|
- if p, ok := msg.(*packet.MiQuotePacket); ok {
|
|
|
|
|
- DispatchRealQuote(p, r)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }()
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
// SetQuoteSubs 设置交易通知订阅信息
|
|
// SetQuoteSubs 设置交易通知订阅信息
|
|
|
func (r *Client) SetTradeNft() {
|
|
func (r *Client) SetTradeNft() {
|
|
|
// global.M2A_LOG.Info("SetTradeNft 11111111111111111111111111111")
|
|
// global.M2A_LOG.Info("SetTradeNft 11111111111111111111111111111")
|
|
@@ -110,48 +76,6 @@ func (r *Client) SetTradeNft() {
|
|
|
}()
|
|
}()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// GetQuoteSubs 获取已订阅行情商品信息列表
|
|
|
|
|
-func (r *Client) GetQuoteSubs() (quoteSubs []request.QuoteGoods) {
|
|
|
|
|
- r.mtx.Lock()
|
|
|
|
|
- defer r.mtx.Unlock()
|
|
|
|
|
-
|
|
|
|
|
- return r.quoteSubs
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// // WriteWsBuf 向客户端发送实时行情
|
|
|
|
|
-// func (r *Client) WriteQuoteWsBuf(buf []byte) (err error) {
|
|
|
|
|
-// if r.quoteWriteChan != nil {
|
|
|
|
|
-// r.quoteWriteChan <- buf
|
|
|
|
|
-// }
|
|
|
|
|
-
|
|
|
|
|
-// return
|
|
|
|
|
-// }
|
|
|
|
|
-
|
|
|
|
|
-// func (r *Client) WriteTradeWsBuf(buf []byte) (err error) {
|
|
|
|
|
-// if r.tradeWriteChan != nil {
|
|
|
|
|
-// r.tradeWriteChan <- buf
|
|
|
|
|
-// } else {
|
|
|
|
|
-// global.M2A_LOG.Info("WriteTradeWsBuf::tradeWriteChan == nil", zap.Any("LoginID", r.LoginID), zap.Any("SessionID", r.SessionID))
|
|
|
|
|
-// }
|
|
|
|
|
-
|
|
|
|
|
-// if r.wsTradeConn != nil {
|
|
|
|
|
-// // r.tradeWriteChan <- buf
|
|
|
|
|
-// } else {
|
|
|
|
|
-// global.M2A_LOG.Info("WriteTradeWsBuf::wsTradeConn == nil", zap.Any("LoginID", r.LoginID), zap.Any("SessionID", r.SessionID))
|
|
|
|
|
-// global.M2A_LOG.Info("当前所有Client----")
|
|
|
|
|
-// for _, item := range Clients {
|
|
|
|
|
-// global.M2A_LOG.Info("client",
|
|
|
|
|
-// zap.Any("LoginID", item.LoginID),
|
|
|
|
|
-// zap.Any("Group", item.Group), zap.Any("SessionID", item.SessionID),
|
|
|
|
|
-// zap.Any("wsTradeConn", item.wsTradeConn), zap.Any("tradeWriteChan", item.tradeWriteChan),
|
|
|
|
|
-// zap.Any("wsQuoteConn", item.wsQuoteConn), zap.Any("quoteWriteChan", item.quoteWriteChan))
|
|
|
|
|
-// }
|
|
|
|
|
-// global.M2A_LOG.Info("----------------")
|
|
|
|
|
-// }
|
|
|
|
|
-
|
|
|
|
|
-// return
|
|
|
|
|
-// }
|
|
|
|
|
-
|
|
|
|
|
// GetAsyncTask 获取目标异步任务
|
|
// GetAsyncTask 获取目标异步任务
|
|
|
// key:SessionId_FuncodeRsp
|
|
// key:SessionId_FuncodeRsp
|
|
|
func (r *Client) GetAsyncTask(key string) (asyncTask *AsyncTask) {
|
|
func (r *Client) GetAsyncTask(key string) (asyncTask *AsyncTask) {
|
|
@@ -195,121 +119,6 @@ func (r *Client) GetAllAsyncTask() *map[string]*AsyncTask {
|
|
|
return &r.asyncTasks
|
|
return &r.asyncTasks
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// **************** Quote WebSocket ****************
|
|
|
|
|
-
|
|
|
|
|
-func (r *Client) SetQuoteWebSocket(ws *websocket.Conn) (err error) {
|
|
|
|
|
- // global.M2A_LOG.Info("行情长连 SetQuoteWebSocket 22222222222222")
|
|
|
|
|
-
|
|
|
|
|
- r.mtx.Lock()
|
|
|
|
|
- defer r.mtx.Unlock()
|
|
|
|
|
-
|
|
|
|
|
- // if r.wsQuoteConn != nil {
|
|
|
|
|
- // r.wsQuoteConn.Close()
|
|
|
|
|
- // }
|
|
|
|
|
- r.wsQuoteConn = ws
|
|
|
|
|
- r.quoteWriteChan = make(chan []byte, 100)
|
|
|
|
|
-
|
|
|
|
|
- // 开始读取客户端发送信息
|
|
|
|
|
- go r.readClientWsQuoteMessage()
|
|
|
|
|
- // 开始推送客户端信息循环
|
|
|
|
|
- go r.writeClientWsQuoteMessage()
|
|
|
|
|
-
|
|
|
|
|
- // r.wsQuoteConn.SetCloseHandler(func(code int, text string) error {
|
|
|
|
|
- // close(r.wsCloseChan)
|
|
|
|
|
- // return nil
|
|
|
|
|
- // })
|
|
|
|
|
-
|
|
|
|
|
- global.M2A_LOG.Info("行情长连客户端接入", zap.Any("LoginID", r.LoginID), zap.Any("SessionID", r.SessionID))
|
|
|
|
|
-
|
|
|
|
|
- return
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// readClientWsQuoteMessage 处理终端发过来的websocket数据
|
|
|
|
|
-// 注意: 阻塞式, 直到websocket关闭才退出
|
|
|
|
|
-func (r *Client) readClientWsQuoteMessage() {
|
|
|
|
|
- for {
|
|
|
|
|
- fmt.Println("readClientWsQuoteMessage start")
|
|
|
|
|
-
|
|
|
|
|
- // 40秒心跳超时
|
|
|
|
|
- r.wsQuoteConn.SetReadDeadline(time.Now().Add(40 * time.Second))
|
|
|
|
|
-
|
|
|
|
|
- mt, msg, err := r.wsQuoteConn.ReadMessage()
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- fmt.Printf("readClientWsQuoteMessage: %v\n", err)
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- switch mt {
|
|
|
|
|
- case websocket.PingMessage:
|
|
|
|
|
- _ = r.wsQuoteConn.WriteMessage(mt, msg)
|
|
|
|
|
- case websocket.CloseMessage:
|
|
|
|
|
- return
|
|
|
|
|
- case websocket.BinaryMessage:
|
|
|
|
|
- if err := r.clientToQuoteAgentMsg(msg); err != nil {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- case websocket.TextMessage:
|
|
|
|
|
- fmt.Println(string(msg))
|
|
|
|
|
- _ = r.wsQuoteConn.WriteMessage(mt, msg)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // FIXME: - 这里要判断是否有问题
|
|
|
|
|
- // select {
|
|
|
|
|
- // case <-r.wsCloseChan:
|
|
|
|
|
- // return
|
|
|
|
|
- // }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// writeClientWsQuoteMessage 由于websocket非线程安全,
|
|
|
|
|
-// 所以由统一协程写入
|
|
|
|
|
-func (r *Client) writeClientWsQuoteMessage() {
|
|
|
|
|
- // defer r.close()
|
|
|
|
|
- // for {
|
|
|
|
|
- // select {
|
|
|
|
|
- // case buf := <-r.quoteWriteChan:
|
|
|
|
|
- // err := r.wsQuoteConn.WriteMessage(websocket.BinaryMessage, buf)
|
|
|
|
|
- // if err != nil {
|
|
|
|
|
- // return
|
|
|
|
|
- // }
|
|
|
|
|
- // case <-r.wsQuoteCloseChan: // 与终端连接关闭信息
|
|
|
|
|
- // return
|
|
|
|
|
- // }
|
|
|
|
|
- // }
|
|
|
|
|
- for {
|
|
|
|
|
- buf, ok := <-r.quoteWriteChan
|
|
|
|
|
- if !ok {
|
|
|
|
|
- // 通道已关闭
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- err := r.wsQuoteConn.WriteMessage(websocket.BinaryMessage, buf)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// clientToQuoteAgentMsg 处理客户端发上来的包
|
|
|
|
|
-func (r *Client) clientToQuoteAgentMsg(msg []byte) error {
|
|
|
|
|
- var p packet.MiQuotePacket
|
|
|
|
|
- err := p.UnPackHead(msg)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- // logger.Logger().Errorf("[%v c->s] invalid packet: %v", r.ProxyId, err)
|
|
|
|
|
- return err
|
|
|
|
|
- }
|
|
|
|
|
- // 长度15 是心跳包, 目前只允许客户端上行心跳包
|
|
|
|
|
- if p.Length == 15 {
|
|
|
|
|
- // logger.Logger().Debugf("%v [%v c->s] %s", r.ClientIP, r.ProxyId, p.HeaderInfo())
|
|
|
|
|
- // 将心跳发回给客户端
|
|
|
|
|
- err = r.wsQuoteConn.WriteMessage(websocket.BinaryMessage, msg)
|
|
|
|
|
- if err != nil {
|
|
|
|
|
- return err
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return nil
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
// **************** Trade WebSocket ****************
|
|
// **************** Trade WebSocket ****************
|
|
|
|
|
|
|
|
func (r *Client) SetTradeWebSocket(ws *websocket.Conn) (err error) {
|
|
func (r *Client) SetTradeWebSocket(ws *websocket.Conn) (err error) {
|