飛信 (Fetion) 曾為中國移動推出的即時通訊服務,提供免費短信功能。早期開源 SDK 多基於反編譯官方客戶端,體積龐大 (30MB+)、相依性複雜,難以在 ASP.NET 等伺服器環境部署。本文分享從零分析協議、用 C# 實作輕量級 SDK (僅含登入、登出、發送短信核心功能) 的關鍵技術點與設計取捨。
libfetion、fetion-php) 理解協議流程。
namespace FetionClient
{
public sealed class FetionClient : IDisposable
{
private readonly string _mobile;
private readonly string _password;
private TcpClient _tcpClient;
private NetworkStream _stream;
private readonly SemaphoreSlim _sendLock = new SemaphoreSlim(1, 1);
public FetionClient(string mobile, string password)
{
_mobile = mobile;
_password = password;
}
public bool Login()
{
_tcpClient = new TcpClient("nav.fetion.com.cn", 5222); // 或其他入口
_stream = _tcpClient.GetStream();
// 1. SSI 註冊 (HTTP over TCP)
// 2. SIP 註冊 + Digest 認證
// 3. 取得 sip:uri、auth-token
return PerformSsiRegistration() && PerformSipRegistration();
}
public bool SendSms(string targetMobile, string content)
{
if (_stream == null) return false;
// 組裝 SIP MESSAGE 請求
var msg = BuildSipMessage(targetMobile, content);
return SendMessage(msg);
}
public void Logout()
{
// 發送 SIP BYE / Registration expire=0
Dispose();
}
public void Dispose()
{
_stream?.Dispose();
_tcpClient?.Dispose();
}
// 內部協議組裝/解析方法略...
}
}
| 難點 | 解法 |
|---|---|
| 編碼與長度計算 | 所有字串統一 Encoding.UTF8.GetBytes(),長度欄位填寫 byte[].Length,避免中文字元長度誤判。 |
| Digest 認證 | 依 RFC 2617 實作 MD5(response) = MD5(MD5(username:realm:password):nonce:MD5(method:uri)),注意 realm、nonce、qop、opaque 解析。 |
| TCP 粘包/拆包 | 協議有明確長度前綴或結束標記 (如 \r\n\r\n),使用 BinaryReader 讀取固定長度或 ReadLine 解析。 |
| 非同步並發 | 單連線串列化發送,使用 SemaphoreSlim 鎖定發送;接收端獨立 Task 循環 ReadAsync 解析推播訊息。 |
| 伺服器端部署 | 無 UI 相依、無 COM 互操作、單一 DLL,適合 ASP.NET Core / Worker Service 容器化部署。 |
using (var fetion = new FetionClient("13800138000", "password123"))
{
if (fetion.Login())
{
fetion.SendSms("13900139000", "測試訊息 from C# SDK");
fetion.Logout();
}
}