1、有更新,还没测完,暂时归档
This commit is contained in:
@ -11,8 +11,6 @@ import (
|
||||
"go-admin/pkg/jsonhelper"
|
||||
"go-admin/pkg/utility"
|
||||
"go-admin/services/proxy"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@ -35,7 +33,7 @@ type BinanceWebSocketManager struct {
|
||||
proxyType string
|
||||
proxyAddress string
|
||||
reconnect chan struct{}
|
||||
isStopped bool
|
||||
isStopped atomic.Bool
|
||||
cancelFunc context.CancelFunc
|
||||
listenKey string
|
||||
reconnecting atomic.Bool
|
||||
@ -44,8 +42,6 @@ type BinanceWebSocketManager struct {
|
||||
forceReconnectTimer *time.Timer
|
||||
}
|
||||
|
||||
// ... (省略中间代码)
|
||||
|
||||
// sendPing 使用锁来确保发送ping时的线程安全
|
||||
func (wm *BinanceWebSocketManager) sendPing() error {
|
||||
wm.mu.Lock()
|
||||
@ -54,18 +50,19 @@ func (wm *BinanceWebSocketManager) sendPing() error {
|
||||
return errors.New("websocket connection is nil")
|
||||
}
|
||||
wm.lastPingTime.Store(time.Now())
|
||||
return wm.ws.WriteMessage(websocket.PingMessage, []byte("ping"))
|
||||
// 使用控制帧发送 Ping,避免与普通消息写入竞争
|
||||
return wm.ws.WriteControl(websocket.PingMessage, []byte("ping"), time.Now().Add(10*time.Second))
|
||||
}
|
||||
|
||||
// Stop 优雅地停止WebSocket管理器
|
||||
func (wm *BinanceWebSocketManager) Stop() {
|
||||
wm.stopOnce.Do(func() {
|
||||
wm.mu.Lock()
|
||||
if wm.isStopped {
|
||||
if wm.isStopped.Load() {
|
||||
wm.mu.Unlock()
|
||||
return
|
||||
}
|
||||
wm.isStopped = true
|
||||
wm.isStopped.Store(true)
|
||||
wm.mu.Unlock()
|
||||
|
||||
if wm.cancelFunc != nil {
|
||||
@ -92,9 +89,11 @@ func (wm *BinanceWebSocketManager) handleReconnect(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-wm.reconnect:
|
||||
if !wm.reconnecting.CompareAndSwap(false, true) {
|
||||
continue // 如果已经在重连,则忽略
|
||||
}
|
||||
// 当收到重连信号时,不再依赖 CompareAndSwap 直接跳过的逻辑。
|
||||
// 之前的实现中,triggerReconnect 已将 reconnecting 标记为 true,
|
||||
// 导致这里 CompareAndSwap 失败而 continue,从而丢失首次重连信号。
|
||||
// 修复:收到信号后直接置位为重连状态并继续执行重连流程,保证首次重连一定发生。
|
||||
wm.reconnecting.Store(true)
|
||||
|
||||
// 在开始重连循环之前,先安全地关闭旧的连接
|
||||
wm.closeConn()
|
||||
@ -108,10 +107,11 @@ func (wm *BinanceWebSocketManager) handleReconnect(ctx context.Context) {
|
||||
default:
|
||||
}
|
||||
|
||||
log.Infof("WebSocket (%s) 正在尝试重连,第 %d 次...", wm.wsType, retryCount+1)
|
||||
log.Infof("WebSocket (%d) 正在尝试重连,第 %d 次...", wm.wsType, retryCount+1)
|
||||
if err := wm.connect(ctx); err == nil {
|
||||
log.Infof("WebSocket (%s) 重连成功", wm.wsType)
|
||||
log.Infof("WebSocket (%d) 重连成功", wm.wsType)
|
||||
wm.reconnecting.Store(false)
|
||||
setLastTime(wm)
|
||||
go wm.startDeadCheck(ctx) // 重连成功后,重新启动假死检测
|
||||
break // 跳出重连循环
|
||||
}
|
||||
@ -163,7 +163,6 @@ func NewBinanceWebSocketManager(wsType int, apiKey, apiSecret, proxyType, proxyA
|
||||
wm := &BinanceWebSocketManager{
|
||||
stopChannel: make(chan struct{}, 10),
|
||||
reconnect: make(chan struct{}, 10),
|
||||
isStopped: false,
|
||||
url: url,
|
||||
wsType: wsType,
|
||||
apiKey: apiKey,
|
||||
@ -174,6 +173,7 @@ func NewBinanceWebSocketManager(wsType int, apiKey, apiSecret, proxyType, proxyA
|
||||
|
||||
// 初始化最后ping时间
|
||||
wm.lastPingTime.Store(time.Now())
|
||||
wm.isStopped.Store(false)
|
||||
|
||||
return wm
|
||||
}
|
||||
@ -210,8 +210,8 @@ func (wm *BinanceWebSocketManager) Restart(apiKey, apiSecret, proxyType, proxyAd
|
||||
wm.proxyType = proxyType
|
||||
wm.proxyAddress = proxyAddress
|
||||
|
||||
if wm.isStopped {
|
||||
wm.isStopped = false
|
||||
if wm.isStopped.Load() {
|
||||
wm.isStopped.Store(false)
|
||||
utility.SafeGo(wm.run)
|
||||
} else {
|
||||
log.Warnf("调用restart")
|
||||
@ -265,6 +265,10 @@ func (wm *BinanceWebSocketManager) run() {
|
||||
errMessage := commondto.WebSocketErr{Time: time.Now()}
|
||||
helper.DefaultRedis.SetString(errKey, jsonhelper.ToJsonString(errMessage))
|
||||
|
||||
// 在主循环前统一启动重连与假死检测,避免重复启动
|
||||
utility.SafeGo(func() { wm.handleReconnect(ctx) })
|
||||
utility.SafeGo(func() { wm.startDeadCheck(ctx) })
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
@ -274,7 +278,7 @@ func (wm *BinanceWebSocketManager) run() {
|
||||
wm.handleConnectionError(errKey, err)
|
||||
|
||||
if wm.isErrorCountExceeded(errKey) {
|
||||
log.Error("连接 %s WebSocket 时出错次数过多,停止 WebSocket 管理器: %v", wm.wsType, wm.apiKey)
|
||||
log.Errorf("连接 %s WebSocket 时出错次数过多,停止 WebSocket 管理器: %v", wm.wsType, wm.apiKey)
|
||||
wm.Stop()
|
||||
return
|
||||
}
|
||||
@ -284,7 +288,7 @@ func (wm *BinanceWebSocketManager) run() {
|
||||
}
|
||||
|
||||
<-wm.stopChannel
|
||||
log.Info("停止 %s WebSocket 管理器...", getWsTypeName(wm.wsType))
|
||||
log.Infof("停止 %s WebSocket 管理器...", getWsTypeName(wm.wsType))
|
||||
wm.Stop()
|
||||
return
|
||||
}
|
||||
@ -315,7 +319,7 @@ func (wm *BinanceWebSocketManager) handleConnectionError(errKey string, err erro
|
||||
}
|
||||
|
||||
// 记录错误日志
|
||||
log.Error("连接 %s WebSocket 时出错: %v, 错误: %v", wm.wsType, wm.apiKey, err)
|
||||
log.Errorf("连接 %s WebSocket 时出错: %v, 错误: %v", wm.wsType, wm.apiKey, err)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -363,34 +367,51 @@ func (wm *BinanceWebSocketManager) connect(ctx context.Context) error {
|
||||
// 连接成功,更新连接时间和ping时间
|
||||
wm.ConnectTime = time.Now()
|
||||
wm.lastPingTime.Store(time.Now())
|
||||
log.Info(fmt.Sprintf("已连接到 Binance %s WebSocket【%s】 key:%s", getWsTypeName(wm.wsType), wm.apiKey, listenKey))
|
||||
setLastTime(wm)
|
||||
log.Infof("已连接到 Binance %s WebSocket【%s】 key:%s", getWsTypeName(wm.wsType), wm.apiKey, listenKey)
|
||||
|
||||
// 设置读超时
|
||||
var readTimeout time.Duration
|
||||
if wm.wsType == 0 {
|
||||
readTimeout = 2 * time.Minute
|
||||
} else {
|
||||
readTimeout = 4 * time.Minute
|
||||
}
|
||||
_ = wm.ws.SetReadDeadline(time.Now().Add(readTimeout))
|
||||
|
||||
// Ping处理
|
||||
wm.ws.SetPingHandler(func(appData string) error {
|
||||
log.Info(fmt.Sprintf("收到 wstype: %v key:%s Ping 消息【%s】", wm.wsType, wm.apiKey, appData))
|
||||
log.Infof("收到 wstype: %d key:%s Ping 消息【%s】", wm.wsType, wm.apiKey, appData)
|
||||
|
||||
for x := 0; x < 5; x++ {
|
||||
if err := wm.ws.WriteControl(websocket.PongMessage, []byte(appData), time.Now().Add(time.Second*10)); err != nil {
|
||||
log.Error("binance 回应pong失败 次数:", strconv.Itoa(x), " err:", err)
|
||||
log.Errorf("binance 回应pong失败 次数:%d err:%v", x, err)
|
||||
time.Sleep(time.Second * 1)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// 更新ping时间和Redis记录
|
||||
// 更新ping时间和Redis记录,并刷新读超时
|
||||
wm.lastPingTime.Store(time.Now())
|
||||
setLastTime(wm)
|
||||
_ = wm.ws.SetReadDeadline(time.Now().Add(readTimeout))
|
||||
return nil
|
||||
})
|
||||
|
||||
// 启动各种协程
|
||||
// Pong处理:收到服务端Pong时刷新心跳与读超时
|
||||
wm.ws.SetPongHandler(func(appData string) error {
|
||||
wm.lastPingTime.Store(time.Now())
|
||||
setLastTime(wm)
|
||||
_ = wm.ws.SetReadDeadline(time.Now().Add(readTimeout))
|
||||
return nil
|
||||
})
|
||||
|
||||
// 启动必要协程(避免在此处重复启动重连与假死检测)
|
||||
utility.SafeGo(func() { wm.startListenKeyRenewal2(ctx) })
|
||||
utility.SafeGo(func() { wm.readMessages(ctx) })
|
||||
utility.SafeGo(func() { wm.handleReconnect(ctx) })
|
||||
utility.SafeGo(func() { wm.startPingLoop(ctx) })
|
||||
utility.SafeGo(func() { wm.startDeadCheck(ctx) }) // 连接成功后立即启动假死检测
|
||||
utility.SafeGo(func() { wm.start24HourReconnectTimer(ctx) }) // 启动24小时强制重连
|
||||
utility.SafeGo(func() { wm.start24HourReconnectTimer(ctx) }) // 启动23小时强制重连
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -398,7 +419,7 @@ func (wm *BinanceWebSocketManager) connect(ctx context.Context) error {
|
||||
// ReplaceConnection 创建新连接并关闭旧连接,实现无缝连接替换
|
||||
func (wm *BinanceWebSocketManager) ReplaceConnection() error {
|
||||
wm.mu.Lock()
|
||||
if wm.isStopped {
|
||||
if wm.isStopped.Load() {
|
||||
wm.mu.Unlock()
|
||||
return errors.New("WebSocket 已停止")
|
||||
}
|
||||
@ -430,7 +451,7 @@ func (wm *BinanceWebSocketManager) ReplaceConnection() error {
|
||||
|
||||
// 设置 ping handler
|
||||
newConn.SetPingHandler(func(appData string) error {
|
||||
log.Infof("收到 Ping(新连接) key:%s msg:%s", wm.apiKey, appData)
|
||||
// log.Infof("收到 Ping(新连接) key:%s msg:%s", wm.apiKey, appData)
|
||||
for x := 0; x < 5; x++ {
|
||||
if err := newConn.WriteControl(websocket.PongMessage, []byte(appData), time.Now().Add(10*time.Second)); err != nil {
|
||||
log.Errorf("Pong 失败 %d 次 err:%v", x, err)
|
||||
@ -456,7 +477,6 @@ func (wm *BinanceWebSocketManager) ReplaceConnection() error {
|
||||
// 步骤 4:启动新连接协程
|
||||
go wm.startListenKeyRenewal2(newCtx)
|
||||
go wm.readMessages(newCtx)
|
||||
go wm.handleReconnect(newCtx)
|
||||
go wm.startPingLoop(newCtx)
|
||||
// go wm.startDeadCheck(newCtx)
|
||||
|
||||
@ -529,8 +549,12 @@ func (wm *BinanceWebSocketManager) getListenKey() (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if listenKey, ok := dataMap["listenKey"]; ok {
|
||||
return listenKey.(string), nil
|
||||
if v, ok := dataMap["listenKey"]; ok {
|
||||
s, ok2 := v.(string)
|
||||
if !ok2 || s == "" {
|
||||
return "", errors.New("listenKey 类型错误或为空")
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
return "", errors.New("listenKey 不存在")
|
||||
@ -544,24 +568,24 @@ func (wm *BinanceWebSocketManager) readMessages(ctx context.Context) {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
if wm.isStopped {
|
||||
if wm.isStopped.Load() {
|
||||
return
|
||||
}
|
||||
|
||||
_, msg, err := wm.ws.ReadMessage()
|
||||
if err != nil {
|
||||
// 检查是否是由于我们主动关闭连接导致的错误
|
||||
if wm.isStopped {
|
||||
if wm.isStopped.Load() {
|
||||
log.Infof("WebSocket read loop gracefully stopped for key: %s", wm.apiKey)
|
||||
return
|
||||
}
|
||||
|
||||
// 如果不是主动关闭,再判断是否是连接关闭错误,并触发重连
|
||||
if strings.Contains(err.Error(), "websocket: close") {
|
||||
log.Error("WebSocket connection closed unexpectedly, triggering reconnect for key: %s. Error: %v", wm.apiKey, err)
|
||||
log.Errorf("WebSocket connection closed unexpectedly, triggering reconnect for key: %s. Error: %v", wm.apiKey, err)
|
||||
wm.triggerReconnect(false)
|
||||
} else {
|
||||
log.Error("Error reading message for key: %s. Error: %v", wm.apiKey, err)
|
||||
log.Errorf("Error reading message for key: %s. Error: %v", wm.apiKey, err)
|
||||
}
|
||||
return // 任何错误发生后都应退出读取循环
|
||||
}
|
||||
@ -611,11 +635,11 @@ func (wm *BinanceWebSocketManager) startPingLoop(ctx context.Context) {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
if wm.isStopped {
|
||||
if wm.isStopped.Load() {
|
||||
return
|
||||
}
|
||||
if err := wm.sendPing(); err != nil {
|
||||
log.Error("主动 Ping Binance 失败:", err)
|
||||
log.Errorf("主动 Ping Binance 失败: %v", err)
|
||||
wm.triggerReconnect(false)
|
||||
return // 退出循环,等待重连
|
||||
}
|
||||
@ -623,24 +647,6 @@ func (wm *BinanceWebSocketManager) startPingLoop(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// 定期删除listenkey 并重启ws
|
||||
// func (wm *BinanceWebSocketManager) startListenKeyRenewal(ctx context.Context, listenKey string) {
|
||||
// time.Sleep(30 * time.Minute)
|
||||
|
||||
// select {
|
||||
// case <-ctx.Done():
|
||||
// return
|
||||
// default:
|
||||
// if err := wm.deleteListenKey(listenKey); err != nil {
|
||||
// log.Error("Failed to renew listenKey: ,type:%v key: %s", wm.wsType, wm.apiKey, err)
|
||||
// } else {
|
||||
// log.Debug("Successfully delete listenKey")
|
||||
// wm.triggerReconnect()
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// 定时续期
|
||||
func (wm *BinanceWebSocketManager) startListenKeyRenewal2(ctx context.Context) {
|
||||
ticker := time.NewTicker(30 * time.Minute)
|
||||
@ -652,12 +658,12 @@ func (wm *BinanceWebSocketManager) startListenKeyRenewal2(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
if wm.isStopped {
|
||||
if wm.isStopped.Load() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := wm.renewListenKey(wm.listenKey); err != nil {
|
||||
log.Error("Failed to renew listenKey: ,type:%v key: %s", wm.wsType, wm.apiKey, err)
|
||||
log.Errorf("Failed to renew listenKey: ,type:%v key: %s err:%v", wm.wsType, wm.apiKey, err)
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
@ -665,36 +671,6 @@ func (wm *BinanceWebSocketManager) startListenKeyRenewal2(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
删除listenkey
|
||||
*/
|
||||
// func (wm *BinanceWebSocketManager) deleteListenKey(listenKey string) error {
|
||||
// client, err := wm.createBinanceClient()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// var resp []byte
|
||||
|
||||
// switch wm.wsType {
|
||||
// case 0:
|
||||
// path := fmt.Sprintf("/api/v3/userDataStream")
|
||||
// params := map[string]interface{}{
|
||||
// "listenKey": listenKey,
|
||||
// }
|
||||
// resp, _, err = client.SendSpotRequestByKey(path, "DELETE", params)
|
||||
|
||||
// log.Debug(fmt.Sprintf("deleteListenKey resp: %s", string(resp)))
|
||||
// case 1:
|
||||
// resp, _, err = client.SendFuturesRequestByKey("/fapi/v1/listenKey", "DELETE", nil)
|
||||
// log.Debug(fmt.Sprintf("deleteListenKey resp: %s", string(resp)))
|
||||
// default:
|
||||
// return errors.New("unknown ws type")
|
||||
// }
|
||||
|
||||
// return err
|
||||
// }
|
||||
|
||||
func (wm *BinanceWebSocketManager) renewListenKey(listenKey string) error {
|
||||
client, err := wm.createBinanceClient()
|
||||
if err != nil {
|
||||
@ -728,19 +704,6 @@ func getWsTypeName(wsType int) string {
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
func getUUID() string {
|
||||
return fmt.Sprintf("%s-%s-%s-%s-%s", randomHex(8), randomHex(4), randomHex(4), randomHex(4), randomHex(12))
|
||||
}
|
||||
|
||||
func randomHex(n int) string {
|
||||
rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
hexChars := "0123456789abcdef"
|
||||
bytes := make([]byte, n)
|
||||
for i := 0; i < n; i++ {
|
||||
bytes[i] = hexChars[rand.Intn(len(hexChars))]
|
||||
}
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动24小时强制重连定时器
|
||||
@ -748,8 +711,9 @@ func randomHex(n int) string {
|
||||
*/
|
||||
func (wm *BinanceWebSocketManager) start24HourReconnectTimer(ctx context.Context) {
|
||||
// Binance要求不到24小时就需要主动断开重连
|
||||
// 设置为23小时50分钟,留出一些缓冲时间
|
||||
duration := 23*time.Hour + 50*time.Minute
|
||||
// 设置为23小时,留出一些缓冲时间
|
||||
// duration := 23 * time.Hour
|
||||
duration := 10 * time.Minute
|
||||
|
||||
wm.forceReconnectTimer = time.NewTimer(duration)
|
||||
defer func() {
|
||||
@ -762,8 +726,8 @@ func (wm *BinanceWebSocketManager) start24HourReconnectTimer(ctx context.Context
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-wm.forceReconnectTimer.C:
|
||||
if !wm.isStopped {
|
||||
log.Warnf("24小时强制重连触发 key:%s wsType:%v", wm.apiKey, wm.wsType)
|
||||
if !wm.isStopped.Load() {
|
||||
log.Warnf("23小时强制重连触发 key:%s wsType:%v", wm.apiKey, wm.wsType)
|
||||
wm.triggerReconnect(true)
|
||||
}
|
||||
}
|
||||
@ -783,7 +747,7 @@ func (wm *BinanceWebSocketManager) startDeadCheck(ctx context.Context) {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
if wm.isStopped {
|
||||
if wm.isStopped.Load() {
|
||||
return
|
||||
}
|
||||
wm.DeadCheck()
|
||||
@ -845,8 +809,3 @@ func (wm *BinanceWebSocketManager) DeadCheck() {
|
||||
wm.triggerReconnect(true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 优化的重连处理逻辑
|
||||
* @param ctx 上下文
|
||||
*/
|
||||
|
||||
@ -97,26 +97,31 @@ func (bnWs *BinanceWs) Subscribe(streamName string, tradeSet models.TradeSet, ca
|
||||
}
|
||||
|
||||
func (bnWs *BinanceWs) exitHandler(c *WsConn) {
|
||||
pingTicker := time.NewTicker(1 * time.Minute)
|
||||
pongTicker := time.NewTicker(30 * time.Second)
|
||||
defer func() {
|
||||
pingTicker.Stop()
|
||||
pongTicker.Stop()
|
||||
c.CloseWs()
|
||||
// exitHandler 维护对底层连接的 Ping/Pong 心跳发送
|
||||
// 修复点:监听 c.close 通道,当连接关闭时退出循环,防止 goroutine 长期驻留导致内存泄漏
|
||||
pingTicker := time.NewTicker(1 * time.Minute)
|
||||
pongTicker := time.NewTicker(30 * time.Second)
|
||||
defer func() {
|
||||
pingTicker.Stop()
|
||||
pongTicker.Stop()
|
||||
c.CloseWs()
|
||||
|
||||
if err := recover(); err != nil {
|
||||
fmt.Printf("CloseWs, panic: %s\r\n", err)
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case t := <-pingTicker.C:
|
||||
c.SendPingMessage([]byte(strconv.Itoa(int(t.UnixNano() / int64(time.Millisecond)))))
|
||||
case t := <-pongTicker.C:
|
||||
c.SendPongMessage([]byte(strconv.Itoa(int(t.UnixNano() / int64(time.Millisecond)))))
|
||||
}
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case <-c.close:
|
||||
// 连接关闭,退出心跳协程
|
||||
return
|
||||
case t := <-pingTicker.C:
|
||||
c.SendPingMessage([]byte(strconv.Itoa(int(t.UnixNano() / int64(time.Millisecond)))))
|
||||
case t := <-pongTicker.C:
|
||||
c.SendPongMessage([]byte(strconv.Itoa(int(t.UnixNano() / int64(time.Millisecond)))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parseJsonToMap(msg []byte) (map[string]interface{}, error) {
|
||||
|
||||
@ -262,11 +262,13 @@ func (ws *WsConn) reconnect() {
|
||||
}
|
||||
}
|
||||
|
||||
// writeRequest 负责写出文本/控制帧以及心跳发送
|
||||
// 修复点:在函数退出时停止 heartTimer,避免底层定时器资源长时间存留
|
||||
func (ws *WsConn) writeRequest() {
|
||||
var (
|
||||
heartTimer *time.Timer
|
||||
err error
|
||||
)
|
||||
var (
|
||||
heartTimer *time.Timer
|
||||
err error
|
||||
)
|
||||
|
||||
if ws.HeartbeatIntervalTime == 0 {
|
||||
heartTimer = time.NewTimer(time.Hour)
|
||||
@ -274,31 +276,37 @@ func (ws *WsConn) writeRequest() {
|
||||
heartTimer = time.NewTimer(ws.HeartbeatIntervalTime)
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ws.close:
|
||||
log.Info("[ws][" + ws.WsUrl + "] close websocket , exiting write message goroutine.")
|
||||
return
|
||||
case d := <-ws.writeBufferChan:
|
||||
err = ws.c.WriteMessage(websocket.TextMessage, d)
|
||||
case d := <-ws.pingMessageBufferChan:
|
||||
err = ws.c.WriteMessage(websocket.PingMessage, d)
|
||||
case d := <-ws.pongMessageBufferChan:
|
||||
err = ws.c.WriteMessage(websocket.PongMessage, d)
|
||||
case d := <-ws.closeMessageBufferChan:
|
||||
err = ws.c.WriteMessage(websocket.CloseMessage, d)
|
||||
case <-heartTimer.C:
|
||||
if ws.HeartbeatIntervalTime > 0 {
|
||||
err = ws.c.WriteMessage(websocket.TextMessage, ws.HeartbeatData())
|
||||
heartTimer.Reset(ws.HeartbeatIntervalTime)
|
||||
}
|
||||
}
|
||||
defer func() {
|
||||
if heartTimer != nil {
|
||||
heartTimer.Stop()
|
||||
}
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
log.Info("[ws][" + ws.WsUrl + "] write message " + err.Error())
|
||||
//time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case <-ws.close:
|
||||
log.Info("[ws][" + ws.WsUrl + "] close websocket , exiting write message goroutine.")
|
||||
return
|
||||
case d := <-ws.writeBufferChan:
|
||||
err = ws.c.WriteMessage(websocket.TextMessage, d)
|
||||
case d := <-ws.pingMessageBufferChan:
|
||||
err = ws.c.WriteMessage(websocket.PingMessage, d)
|
||||
case d := <-ws.pongMessageBufferChan:
|
||||
err = ws.c.WriteMessage(websocket.PongMessage, d)
|
||||
case d := <-ws.closeMessageBufferChan:
|
||||
err = ws.c.WriteMessage(websocket.CloseMessage, d)
|
||||
case <-heartTimer.C:
|
||||
if ws.HeartbeatIntervalTime > 0 {
|
||||
err = ws.c.WriteMessage(websocket.TextMessage, ws.HeartbeatData())
|
||||
heartTimer.Reset(ws.HeartbeatIntervalTime)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Info("[ws][" + ws.WsUrl + "] write message " + err.Error())
|
||||
//time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ws *WsConn) Subscribe(subEvent interface{}) error {
|
||||
|
||||
Reference in New Issue
Block a user