Asp.net core 如何在asp.net core中写入Response.Body时检测客户端何时关闭流
我试图编写一个无限长的响应体,并检测客户端何时断开连接,以便停止编写。我习惯于在客户端关闭连接时出现套接字异常或类似情况,但直接写入Response.Body时似乎不会出现这种情况。我可以关闭客户端应用程序,服务器端只需继续编写。我已经在下面包含了相关代码。完全有可能有更好的方法,但我想到了这一点。基本上,我有一个实时视频饲料应该永远持续下去。我以分块内容(无内容长度,在每个视频帧后刷新)的形式向ResponseBook写信。视频帧是通过程序中其他地方的事件回调接收的,因此我订阅控制器方法中的事件,然后强制它在等待任务中保持打开状态。延迟循环,以便响应流不会关闭。H264PacketReceived的回调正在将数据格式化为流式mp4文件,并将其写入响应流。这一切似乎都很好,我可以用ffmpeg或chrome播放实时流,但当我关闭客户端应用程序时,我没有得到任何异常或任何东西。它只是不断地写入流,没有任何错误Asp.net core 如何在asp.net core中写入Response.Body时检测客户端何时关闭流,asp.net-core,Asp.net Core,我试图编写一个无限长的响应体,并检测客户端何时断开连接,以便停止编写。我习惯于在客户端关闭连接时出现套接字异常或类似情况,但直接写入Response.Body时似乎不会出现这种情况。我可以关闭客户端应用程序,服务器端只需继续编写。我已经在下面包含了相关代码。完全有可能有更好的方法,但我想到了这一点。基本上,我有一个实时视频饲料应该永远持续下去。我以分块内容(无内容长度,在每个视频帧后刷新)的形式向ResponseBook写信。视频帧是通过程序中其他地方的事件回调接收的,因此我订阅控制器方法中的事
public class LiveController : ControllerBase
{
[HttpGet]
[Route("/live/{cameraId}/{stream}.mp4")]
public async Task GetLiveMP4(Guid cameraId, int stream)
{
try
{
Response.StatusCode = 200;
Response.ContentType = "video/mp4";
Response.Headers.Add("Cache-Control", "no-store");
Response.Headers.Add("Connection", "close");
ms = Response.Body;
lock (TCPVideoReceiver.CameraStreams)
{
TCPVideoReceiver.CameraStreams.TryGetValue(cameraId, out cameraStream);
}
if (this.PacketStream == null)
{
throw new KeyNotFoundException($"Stream {cameraId}_{stream} not found");
}
else
{
connected = true;
this.PacketStream.H264PacketReceived += DefaultStream_H264PacketReceived;
this.PacketStream.StreamClosed += PacketStream_StreamClosed;
}
while(connected)
{
await Task.Delay(1000);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
connected = false;
this.PacketStream.H264PacketReceived -= DefaultStream_H264PacketReceived;
this.PacketStream.StreamClosed -= PacketStream_StreamClosed;
}
}
private bool connected = false;
private PacketStream PacketStream;
private Mp4File mp4File;
private Stream ms;
private async void PacketStream_StreamClosed(PacketStream source)
{
await Task.Run(() =>
{
try
{
Console.WriteLine($"Closing live stream");
connected = false;
ms.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
});
}
private async void DefaultStream_H264PacketReceived(PacketStream source, H264Packet packet)
{
try
{
if (mp4File == null && packet.IsIFrame)
{
mp4File = new Mp4File(null, packet.sps, packet.pps);
var _p = mp4File.WriteHeader(0);
await ms.WriteAsync(mp4File.buffer, 0, _p);
}
if (mp4File != null)
{
var _p = mp4File.WriteFrame(packet, 0);
var start = mp4File._moofScratchIndex - _p;
if (_p > 0)
{
await ms.WriteAsync(mp4File._moofScratch, start, _p);
await ms.FlushAsync();
}
}
return;
}
catch (Exception ex)
{
connected = false;
Console.WriteLine(ex.ToString());
}
}
回答我自己的问题 当客户端断开mvc核心连接时,设置取消令牌HttpContext.RequestAborted 通过监视和/或使用该取消令牌,您可以检测到断开连接并清除所有内容 也就是说,可以通过创建封装事件处理(生产者/消费者)的自定义流来改进整个设计。然后控制器的动作可以减少到
return File(new MyCustomStream(cameraId, stream), "video/mp4");
File方法已经监视了取消令牌,一切都如您所期望的那样工作