.NET异步Socket大慢流场景下,客户端中途停止接收传输的实现方案
嘿,这个场景我太熟悉了!异步Socket处理这种慢节奏的仪器数据流,还要能随时叫停接收循环,核心就是给你的异步流程加个可取消的控制开关,既优雅又安全,完全不用粗暴地直接断开Socket。
核心方案:用CancellationToken控制异步接收循环
我们可以借助.NET的CancellationTokenSource来给接收流程发送停止信号,让客户端能优雅终止接收循环,还能按需通知服务器停止发送数据流。
1. 改造异步接收逻辑,加入取消支持
MSDN的原生异步Socket示例是无限循环接收,我们给它加上取消令牌的判断,每次发起异步接收前先检查是否需要停止,同时用ReceiveAsync的Task版本(比传统APM模式更易结合取消逻辑):
private CancellationTokenSource _receiveCts; private Socket _clientSocket; // 启动接收数据流的方法 public async Task StartReceivingDataAsync() { _receiveCts = new CancellationTokenSource(); var buffer = new byte[1024]; // 匹配你的单条小消息大小 try { while (!_receiveCts.Token.IsCancellationRequested) { // 绑定取消令牌,接收过程中收到取消信号会抛出OperationCanceledException var receiveBytes = await _clientSocket.ReceiveAsync(buffer, SocketFlags.None, _receiveCts.Token); if (receiveBytes == 0) { // 服务器主动关闭连接,正常退出循环 Console.WriteLine("服务器已断开连接"); break; } // 处理单条收到的消息(比如转成字符串解析) var message = Encoding.ASCII.GetString(buffer, 0, receiveBytes); Console.WriteLine($"收到仪器数据: {message}"); } } catch (OperationCanceledException) { // 捕获取消异常,这是主动停止的正常流程 Console.WriteLine("已主动停止接收数据流"); } finally { // 确保清理Socket资源 _clientSocket?.Shutdown(SocketShutdown.Both); _clientSocket?.Close(); _receiveCts?.Dispose(); } }
2. 实现一键停止接收的方法
只需要触发CancellationTokenSource的取消信号,就能立刻终止接收循环:
public void StopReceivingData() { if (_receiveCts != null && !_receiveCts.IsCancellationRequested) { _receiveCts.Cancel(); } }
3. 可选:通知服务器停止发送数据流
如果需要服务器也同步停止输出数据,可以在调用停止方法前,给服务器发一条“停止指令”:
public async Task SendStopCommandToServerAsync() { var stopCommand = Encoding.ASCII.GetBytes("STOP_TRANSMISSION"); await _clientSocket.SendAsync(stopCommand, SocketFlags.None); }
服务器收到这条指令后,就可以停止发送数据流,双方完成优雅终止。
关键注意点
- 别粗暴关闭Socket:直接调用
Close()会导致正在进行的异步接收抛出未处理异常,还可能丢失最后几条传输中的消息,用取消令牌是更安全的方式。 - 处理服务器主动断开:如果仪器/服务器意外断开,
ReceiveAsync会返回0字节,这时候要正常退出循环,避免无限等待。 - 资源一定要清理:在
finally块里务必关闭Socket、释放CancellationTokenSource,防止内存泄漏。
内容的提问来源于stack exchange,提问作者paparazzo
相关产品推荐
相关产品推荐

