C# - 三种流式响应机制详解
C# - 三种流式响应机制详解
在现代Web应用中,实时数据传输和高效的数据流处理变得越来越重要。ASP.NET Core提供了多种流式响应机制,以满足不同场景下的需求。
1. Server-Sent Events (SSE)
适用场景
- 实时更新的应用,如聊天应用、实时监控、新闻推送等。
- 单向通信(服务器到客户端)。
服务器端实现
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
namespace StreamedResponseExample.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class StreamController : ControllerBase
{
[HttpGet("sse")]
public async Task StreamSse()
{
Response.ContentType = "text/event-stream";
Response.Headers.Add("Cache-Control", "no-cache");
Response.Headers.Add("Connection", "keep-alive");
var messages = new string[] {
"Hello, ",
"this is an SSE message!",
"Here's another message."
};
foreach (var message in messages)
{
await Response.WriteAsync($"data: {message}\n\n");
await Response.Body.FlushAsync(); // 强制立即发送
await Task.Delay(1000); // 每条消息间隔1秒
}
}
}
}
客户端实现
<div id="messages"></div>
<script>
// 创建SSE连接
const eventSource = new EventSource('https://localhost:7148/api/stream/sse');
// 监听消息事件
eventSource.onmessage = function (event) {
const messageContainer = document.getElementById('messages');
const newMessage = document.createElement('p');
newMessage.textContent = event.data;
messageContainer.appendChild(newMessage);
// 滚动到最新消息
messageContainer.scrollTop = messageContainer.scrollHeight;
};
// 监听打开连接事件
eventSource.onopen = function () {
console.log("连接已打开");
};
// 监听错误事件
eventSource.onerror = function (error) {
console.error("发生错误", error);
eventSource.close(); // 关闭连接
};
</script>
2. WebSocket
适用场景
- 需要双向实时通信的应用,如在线聊天、多人游戏等。
服务器端实现
using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
namespace StreamedResponseExample.Hubs
{
public class ChatHub : Hub
{
public async Task SendMessage(string message)
{
await Clients.All.SendAsync("ReceiveMessage", message);
}
}
}
[Route("api/[controller]")]
[ApiController]
public class StreamController : ControllerBase
{
private readonly IHubContext<ChatHub> _hubContext;
public StreamController(IHubContext<ChatHub> hubContext)
{
_hubContext = hubContext;
}
[HttpGet("websocket")]
public async Task WebSocketStream()
{
var messages = new string[] {
"Hello, ",
"this is a WebSocket message!",
"Here's another one."
};
foreach (var message in messages)
{
await _hubContext.Clients.All.SendAsync("ReceiveMessage", message);
await Task.Delay(1000); // 每条消息间隔1秒
}
}
}
客户端实现
<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/5.0.13/signalr.min.js"></script>
<script>
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chatHub")
.build();
connection.on("ReceiveMessage", function (message) {
console.log("Received message: ", message);
const contentDiv = document.getElementById('content');
contentDiv.innerHTML += message + '<br>';
});
connection.start().catch(function (err) {
return console.error(err.toString());
});
</script>
<body>
<div id="content"></div>
</body>
3. 分块传输编码
Chunked Transfer Encoding
适用场景
- 大数据流的分块传输,支持逐步发送响应。
服务器端实现
using Microsoft.AspNetCore.Mvc;
using System.Text;
using System.Threading.Tasks;
namespace StreamedResponseExample.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class StreamController : ControllerBase
{
[HttpGet("chunked")]
public async Task ChunkedResponse()
{
Response.ContentType = "text/plain";
var phrases = new string[] {
"This is ",
"a chunked ",
"response! ",
"Enjoy it."
};
foreach (var phrase in phrases)
{
byte[] buffer = Encoding.UTF8.GetBytes(phrase);
await Response.Body.WriteAsync(buffer, 0, buffer.Length);
await Response.Body.FlushAsync(); // 强制发送数据块
await Task.Delay(1000); // 每块之间的延时
}
}
}
}
客户端实现
<body>
<div id="content"></div>
<script>
fetch('https://localhost:7128/api/stream/chunked')
.then(response => {
const reader = response.body.getReader();
const decoder = new TextDecoder();
const contentDiv = document.getElementById('content');
function readChunk() {
reader.read().then(({ done, value }) => {
if (done) return;
contentDiv.innerHTML += decoder.decode(value, { stream: true }) + '<br>';
readChunk(); // 继续读取下一个数据块
});
}
readChunk();
});
</script>
</body>
结论
- SSE:适合服务器向客户端推送数据(单向流),专门用于事件推送。
- WebSocket:适合需要双向实时通信的应用。
- 分块传输编码:适合大数据流的分块传输,支持逐步发送响应。
本文作者:ShenHaoCore
本文链接:https://www.cnblogs.com/ShenhaoCore/p/18712754
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步