C# 中 WebSocket 與 SignalR實時通信的兩種方案
在現(xiàn)代 Web 應用中,實時通信變得越來越重要。無論是聊天應用、在線游戲、股票行情推送還是協(xié)作編輯工具,都需要服務器能夠主動向客戶端推送數(shù)據(jù)。在 .NET 生態(tài)系統(tǒng)中,WebSocket 和 SignalR 是實現(xiàn)這一功能的兩個主要方案。
本文將對這兩種技術進行比較,分析它們的異同點和使用場景,并提供簡單示例代碼幫助你快速上手。
一、什么是 WebSocket?
WebSocket 是 HTML5 提供的一種全雙工通信協(xié)議,允許客戶端與服務器之間建立持久連接,實現(xiàn)雙向?qū)崟r通信。相比傳統(tǒng)的 HTTP 請求-響應模式,WebSocket 更加高效,適合需要頻繁交互的應用。
WebSocket 特點:
- 基于 TCP 協(xié)議
- 支持雙向通信
- 連接是長連接(保持打開)
- 輕量級,性能高
- 需要手動管理連接和消息處理
使用場景:
- 實時數(shù)據(jù)推送(如股票行情)
- 在線多人游戲
- 多人協(xié)作編輯
- IoT 設備通信等
二、什么是 SignalR?
SignalR 是微軟開發(fā)的一個基于 .NET 的庫,它簡化了實時通信的實現(xiàn)。SignalR 內(nèi)部封裝了多種傳輸方式(包括 WebSocket、Server-Sent Events、長輪詢等),并根據(jù)瀏覽器和網(wǎng)絡環(huán)境自動選擇最優(yōu)的方式。
SignalR 特點:
- 抽象了底層通信細節(jié)
- 支持跨平臺(.NET Core / .NET 6+)
- 自動降級兼容性差的瀏覽器
- 提供 Hub 模式,易于組織業(yè)務邏輯
- 可集成到 ASP.NET Core 中
使用場景:
- 快速構(gòu)建實時功能(無需關注底層通信細節(jié))
- Web 應用中的通知系統(tǒng)
- 即時通訊(IM)應用
- 實時儀表盤、狀態(tài)監(jiān)控
三、WebSocket vs SignalR 對比
| 特性 | WebSocket | SignalR |
|---|---|---|
| 通信方式 | 全雙工 | 全雙工(通過封裝) |
| 是否需要手動處理連接 | ? 需要 | ? 不需要 |
| 是否支持多路復用 | ? 不支持 | ? 支持(Hub) |
| 是否支持自動降級 | ? 不支持 | ? 支持(長輪詢等) |
| 開發(fā)復雜度 | 較高 | 較低 |
| 性能 | 高 | 略低于 WebSocket |
| 適合場景 | 高性能、定制化通信 | 快速開發(fā)、通用實時功能 |
四、示例代碼
示例 1:WebSocket 服務端 + 客戶端(.NET)
服務端(控制臺程序)
using System;
using System.Net;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://localhost:5000/");
listener.Start();
Console.WriteLine("WebSocket Server started on http://localhost:5000");
while (true)
{
HttpListenerContext context = await listener.GetContextAsync();
if (context.Request.IsWebSocketRequest)
{
WebSocketContext webSocketContext = await context.AcceptWebSocketAsync(null);
_ = HandleWebSocketConnection(webSocketContext.WebSocket);
}
else
{
context.Response.StatusCode = 400;
context.Response.Close();
}
}
}
private static async Task HandleWebSocketConnection(WebSocket socket)
{
byte[] buffer = new byte[1024 * 4];
while (socket.State == WebSocketState.Open)
{
WebSocketReceiveResult result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
Console.WriteLine($"Received: {message}");
// Echo back the message
byte[] response = Encoding.UTF8.GetBytes($"Echo: {message}");
await socket.SendAsync(new ArraySegment<byte>(response), WebSocketMessageType.Text, true, CancellationToken.None);
}
}
}客戶端(JavaScript)
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Client</title>
</head>
<body>
<input type="text" id="messageInput" placeholder="Enter message" />
<button onclick="sendMessage()">Send</button>
<div id="output"></div>
<script>
const ws = new WebSocket('ws://localhost:5000');
ws.onmessage = function (event) {
document.getElementById('output').innerText += event.data + '\n';
};
function sendMessage() {
const input = document.getElementById('messageInput');
const message = input.value;
ws.send(message);
input.value = '';
}
</script>
</body>
</html>示例 2:SignalR 服務端 + 客戶端(ASP.NET Core)
服務端(Startup.cs 或 Program.cs)
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddSignalR();
var app = builder.Build();
app.MapHub<ChatHub>("/chatHub");
app.Run();
public class ChatHub : Hub
{
public async Task Send(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}客戶端(JavaScript)
<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/5.0.13/signalr.min.js"></script>
<input type="text" id="userInput" placeholder="User" />
<input type="text" id="messageInput" placeholder="Message" />
<button onclick="sendMessage()">Send</button>
<div id="chat"></div>
<script>
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chatHub")
.build();
connection.on("ReceiveMessage", function (user, message) {
const msg = `${user}: ${message}`;
document.getElementById("chat").innerHTML += `<p>${msg}</p>`;
});
connection.start().catch(function (err) {
return console.error(err.toString());
});
function sendMessage() {
const user = document.getElementById("userInput").value;
const message = document.getElementById("messageInput").value;
connection.invoke("Send", user, message).catch(function (err) {
return console.error(err.toString());
});
document.getElementById("messageInput").value = "";
}
</script>五、總結(jié)
| 場景 | 推薦技術 |
|---|---|
| 高性能、低延遲、自定義協(xié)議 | WebSocket |
| 快速開發(fā)、通用實時功能 | SignalR |
| 瀏覽器兼容性要求高 | SignalR |
| 需要精細控制通信過程 | WebSocket |
如果你正在開發(fā)一個簡單的聊天室或通知系統(tǒng),SignalR 是更好的選擇;而如果你需要構(gòu)建一個高性能、低延遲的物聯(lián)網(wǎng)通信系統(tǒng),WebSocket 更合適。
六、延伸閱讀
到此這篇關于C# 中 WebSocket 與 SignalR:實時通信的兩種選擇的文章就介紹到這了,更多相關C# WebSocket 與 SignalR實時通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C#實現(xiàn)的ACCESS數(shù)據(jù)庫操作類完整實例
這篇文章主要介紹了C#實現(xiàn)的ACCESS數(shù)據(jù)庫操作類,結(jié)合完整實例形式分析了C#針對access數(shù)據(jù)庫增刪改查、事務、結(jié)果處理等相關操作技巧,需要的朋友可以參考下2017-05-05

