必须用SendAsync。同步Send在连接异常时会阻塞线程,异步可避免阻塞并支持超时控制;心跳应答需超时重试+连续失败计数,TCP.Connected不可靠;KeepAlive不能替代应用层心跳;心跳与业务数据须协议分离。心跳包该用 Send 还是 SendAsync?必须用 SendAsync。同步 Send 在连接已断但 TCP 状态未及时回收(如对方突然掉电、NAT 超时)时会卡住线程,甚至阻塞整个心跳定时器。异步发送能避免阻塞,也方便配合 CancellationToken 控制超时。常见错误现象:心跳线程卡死、CPU 占用突增、后续所有消息无法发出但日志里没报错。心跳数据尽量小,推荐固定 1 字节(如 0xFF),避免触发 Nagle 算法延迟务必设置 Socket.SendTimeout = 3000,并捕获 SocketException 中的 ErrorCode == 10054(连接被远程重置)或 10053(软件导致连接中止)不要在 SendAsync 回调里直接重发------需先检查 args.SocketError == SocketError.Success怎么判断"连接还活着"而不是"只是没回包"?单靠发包不等于连通。真实可用的心跳必须有应答 + 超时重试 + 连续失败计数。TCP 层的 Connected 属性几乎没用------它只反映上一次操作是否成功,不是实时状态。使用场景:移动网络切换、WiFi 断连再重连、防火墙静默丢弃 ACK。客户端发心跳后,启动独立 Task.Delay(5000, token) 等待服务端回包;超时即视为异常连续 3 次心跳无响应(非超时,是根本没收到任何数据),才触发断连逻辑服务端收到心跳后必须立刻 Send 一个确认字节(如 0x00),不能攒着或延迟回复禁用 Socket.NoDelay = false(即开启 Nagle),否则小包会被缓冲,心跳响应延迟不可控KeepAlive 选项能不能代替应用层心跳?不能。系统级 KeepAlive(通过 SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true) 启用)只探测链路层是否可达,且默认间隔长达 2 小时,对业务级连接保活毫无意义。 AI智研社 AI智研社是一个专注于人工智能领域的综合性平台
相关推荐
码力斜杠哥1 小时前
Rust初习录(6)Rust的 if 玩法Jetev1 小时前
不同品牌SSD对HTML函数工具加载速度影响大吗_存储测试汇总【汇总】SelectDB技术团队1 小时前
时间序列近邻关联性能实测:Doris ASOF JOIN 领先 ClickHouse、DuckDBgf13211111 小时前
python_【更新已发送的消息卡片】Traving Yu1 小时前
向量数据库Milvuskeineahnung23451 小时前
PyTorch SymNode 為何找不到方法實作?──sizes_strides_methods 動態安裝機制解析2501_901006471 小时前
golang如何使用DTM分布式事务框架_golang DTM分布式事务框架使用方法2501_901200532 小时前
Golang如何做Clean Architecture_Golang整洁架构教程【详解】咖啡里的茶i2 小时前
实验三 数据完整性实验