# Socket 收發與壅塞處理
`TikTok.js` 的聊天、廣告、觀眾更新與心跳統一由 `ScriptLib/socket/transport.mjs`(`SocketTransport`)發送;訊息去重、端點與扇出在 `ScriptLib/socket/`(`MessageDedup`、`SocketEndpoint`、`SocketHub`)。
`MessageDedup` 除了使用者與第一行內容,可帶 opt-in `variant`。目前只有 `isTest` 測試訊息使用 `test:<頭貼 URL>`,讓同文同人但換頭貼的測試可以通過;一般訊息不帶 variant,維持原本跨路徑去重。
`remaining(username, message, variant)` 回傳目前保護剩餘毫秒;測試訊息會把結果經 IPC 回主服務,並用 `testId` 對應到 `/status/stream/test-results`,因此能顯示精確的冷卻時間。重複的測試訊息不會再刷新 TTL。
測試派發可分別關閉 socket/通知;`Notifier.notify` 回傳 `[{ channel, ok }]`,子程序再彙整成 `sent`/`partial`/`failed`/`nochannels`。一般聊天仍同時走 socket 與通知,不受測試選項影響。
所有平台的 StreamMessage 會附上 `session: { joins, likes, chats, follows, subscriptions, gifts, peakViewers }`,供 monitor 顯示本場累計;一般 socket 端點可忽略此欄位。`peakViewers` 是合併觀眾數的場次峰值,不是目前人數。點讚通知以 3 秒窗口合併,monitor 的逐筆點讚列不受影響。Socket 端點可在程式執行中透過 runtime 頁開關;關閉時保留端點設定但停止連線與送出。
通訊格式維持 UTF-8 JSON,每筆以換行結尾,不需修改既有接收端協定。
## 預設限制
- Node.js 待送佇列:最多 200 筆、合計 1 MiB;容量不足時淘汰最舊資料。
- 待送訊息有效期限:30 秒,在入列及發送前移除過期資料。
- 待送觀眾更新、心跳:同類型只保留最新一筆。
- 單筆 JSON:最多 256 KiB,接收端遇到超大資料會關閉連線。
- `write(false)`:該筆已由 Node.js 接受,後續訊息等待 `drain`,不重送該筆。
- 連線建立或等待 `drain` 超過 15 秒:關閉並重新連線。
- 重連間隔:15 秒;連續失敗超過 10 次後,每次增加 5 秒,最多 5 分鐘。
- 關閉:最多等待 2 秒,避免程式結束時卡住。
- Python 接收佇列:最多 200 筆,滿時淘汰最舊資料,不阻塞接收執行緒。
- Python 每次畫面更新:最多處理 20 筆,或在約 4ms 後停止取下一筆。
單筆處理無法中途打斷,因此耗時的單筆工作仍可能超過此預算。
這些限制優先維持直播訊息的即時性。大量壅塞、超時或斷線時,可能捨棄訊息,
不是無損訊息儲存。尚未交給 Socket 的佇列資料會留待重連;已交给 TCP 的資料
沒有應用層 ACK,無法確認對方是否已處理,因此不會自動重送,以免重複顯示。
Node.js `[Socket]` 日誌每 10 秒最多回報一次佇列筆數、位元組、淘汰數與重連數。
淘汰數包含被更新狀態取代的資料。Python 佇列滿載日誌同樣節流。
## Python 接收端(live_engine)
`OtherTool/live_engine/network/socket_server.py` 是接收端,負責傾聽並把訊息交給疊加層:
- 綁定使用 `SO_REUSEADDR`,方便重啟後快速重綁;若埠被佔用則寫入錯誤日誌、送出 `SystemEvent` `socket_error`(引擎會記錄),並每 5 秒重試,不會靜默失效。
- 每 20 秒主動送出 `{"type":"keepalive"}`;Node 端 `SocketTransport` 收到後回覆 `heartbeat`。超過 60 秒未收到任何資料的連線會被主動關閉,避免半開連線讓連線計數與計時器卡住。
- 同時最多接受 8 條連線,超出者直接拒絕並記錄;連線進出(含 peer 位址)都會寫入日誌。
- 接收執行緒只將訊息放入上限 200 筆的佇列(滿載淘汰最舊),畫面更新端每幀最多處理 20 筆或約 4ms。
## 驗證
```sh
node --test Test/socket_transport.test.mjs
node --check TikTok.js
python -B -m unittest discover -s Test -p socket_receiver_test.py
```
測試不啟動直播服務,不需登入平台。涵蓋分包/黏包、UTF-8 跨封包、格式錯誤、
訊息上限、背壓、過期資料、斷線補發、連線與關閉逾時,以及本機 TCP 慢速接收。