遠程主機主動關閉現有連接。(srcIP, srcPort, dstIP, dstPort) 唯一標識。若多台設備真實源 IP 相同(NAT 後),但源端口不同,理論上不會衝突。new Socket()、發完不關閉,短連接風暴加劇端口耗盡。// Android 伪代碼
Socket socket = new Socket(serverIp, port);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
while (running) {
out.writeBytes(data);
out.flush();
Thread.sleep(1000);
}
// 退出時關閉
減少握手開銷,避免 TIME_WAIT 堆積。
DeviceID(如 MAC、Android ID、隨機 UUID)。ConcurrentHashMap<String, Socket> 維護設備連接,同一 DeviceID 重複登錄踢舊連接。NetworkStream.Read 返回 0 表示對端正常關閉,-1/異常表示斷開,需統一處理。// 使用 async/await 替換線程池,避免大量線程
private async Task ListenAsync() {
while (true) {
var client = await listener.AcceptTcpClientAsync();
_ = HandleClientAsync(client); // 火燄忘記模式
}
}
private async Task HandleClientAsync(TcpClient client) {
using (client)
using (var stream = client.GetStream()) {
var buffer = new byte[4096];
while (true) {
int read = await stream.ReadAsync(buffer, 0, buffer.Length);
if (read == 0) break; // 正常關閉
var msg = Encoding.UTF8.GetString(buffer, 0, read);
ProcessMessage(msg);
}
}
}
核心問題在於網絡層 NAT 衝突 + 應用層短連接濫用。長連接 + 設備唯一標識 + 內網穿透/雲端中轉 是穩健方案。若無法改變網絡環境,至少在應用層實現設備識別與重連機制。