首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

DotMSN 機器人自動斷線問題根因與 Ping 保活完整解決方案

     編輯:關於.NET

使用 DotMSN 開發 MSN 機器人時,機器人在閒置一段時間後會**無聲斷線**:無任何事件通知,Connected 屬性仍為 true,Owner.Status 正常,極難排查。本文揭露根因並提供 **自訂 PingMessage 保活** 完整實作。

問題現象與根因分析

  • MSN 伺服器若偵測客戶端長時間無封包往來,會**主動切斷 TCP 連線**但不發送 FIN/RST (半開連線)。
  • DotMSN 預設未實作應用層心跳機制,導致客戶端不知連線已失效。
  • MSNP 協定定義 PNG\r\n (Ping) 指令,伺服器回覆 QNG\r\n (Pong),可作為保活探針。

嘗試 1:直接用 NSMessage 發送 Ping (失敗)


void SendPing()
{
    // NSMessage 會自動附加 TransactionID、參數、空格、換行
    // 實際發送: "PNG 123 \r\n" —— 不符合協定純粹 "PNG\r\n"
    NSMessage message = new NSMessage("PNG\r\n", new string[] { });
    messenger.NameserverProcessor.SendMessage(message);
}

結果:雖觸發 PingAnswer 事件 (伺服器有回應),但同時觸發 SignedOff 被踢下線。**原因**:NSMessage.GetBytes() 序列化格式包含額外欄位,破壞 Ping 指令純粹性。

解決方案:自訂 PingMessage 繼承 NSMessage


using XihSolutions.DotMSN.Core;

public class PingMessage : NSMessage
{
    public override byte[] GetBytes()
    {
        // 純粹發送 "PNG\r\n",無 TransactionID、無參數、無額外空格
        return System.Text.Encoding.UTF8.GetBytes("PNG\r\n");
    }
}

修正後的發送邏輯


void SendPing()
{
    messenger.NameserverProcessor.SendMessage(new PingMessage());
}

測試:登入後呼叫 SendPing() → PingAnswer 觸發,**不再觸發 SignedOff**,連線維持正常。

完整保活機制:Timer 定時發送


using System.Timers;

public class MsnBot
{
    private readonly Timer _keepAliveTimer;
    private readonly Messenger _messenger;

    public MsnBot(Messenger messenger)
    {
        _messenger = messenger;
        _keepAliveTimer = new Timer(120_000) // 每 2 分鐘
        {
            AutoReset = true,
            Enabled = false
        };
        _keepAliveTimer.Elapsed += (s, e) => SendPing();
    }

    public void Start()
    {
        _messenger.Login();
        _keepAliveTimer.Start();
    }

    public void Stop()
    {
        _keepAliveTimer.Stop();
        _messenger.Logout();
    }

    private void SendPing()
    {
        try
        {
            _messenger.NameserverProcessor.SendMessage(new PingMessage());
        }
        catch (Exception ex)
        {
            // 記錄錯誤,避免 Timer 執行緒崩潰
            Console.WriteLine($"Ping 發送失敗: {ex.Message}");
        }
    }
}

注意事項與限制

  • 測試環境:在預期斷線間隔內 (甚至更長) 驗證有效,**不保證全天候 100% 存活**。
  • 其他斷線原因:網路波動、伺服器維護、帳號異地登入等需額外處理 (重連邏輯、錯誤事件訂閱)。
  • DotMSN 版本差異:舊版可能無 NameserverProcessor,需參考原始碼調整存取路徑。

協定層面補充

指令格式方向用途
PNGPNG\r\nClient → Server心跳探針
QNGQNG\r\nServer → Client心跳回應
CHLCHL \r\nServer → Client挑戰認證
QRYQRY \r\nClient → Server查詢用戶/群組

總結

DotMSN 機器人斷線核心在於**缺乏應用層心跳**。關鍵突破點:NSMessage 序列化格式不符 Ping 指令規範 → **繼承並覆寫 GetBytes() 產出純粹 PNG\r\n** → 搭配 Timer 定時發送。此方案輕量、無侵入性、相容現有 DotMSN 架構,是解決 MSN 機器人閒置斷線的標準做法。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved