ASP.NET Core'da WebSockets desteği
Uyarı
ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.
Bu makalede, ASP.NET Core'da WebSockets ile çalışmaya başlama açıklanmaktadır. WebSocket (RFC 6455), TCP bağlantıları üzerinden iki yönlü kalıcı iletişim kanalları sağlayan bir protokoldür. Sohbet, pano ve oyun uygulamaları gibi hızlı, gerçek zamanlı iletişimden yararlanan uygulamalarda kullanılır.
Örnek kodu görüntüleme veya indirme (indirme, çalıştırma).
Http/2 WebSockets desteği
HTTP/2 üzerinden WebSockets kullanmak aşağıdaki gibi yeni özelliklerden yararlanır:
- Üst bilgi sıkıştırma.
- Sunucuya birden çok istekte bulunurken gereken süreyi ve kaynakları azaltan çoğullama.
Bu desteklenen özellikler tüm HTTP/2 özellikli platformlarda Kestrel kullanılabilir. Sürüm anlaşması tarayıcılarda ve Kestrel'de otomatiktir, bu nedenle yeni API'ler gerekmez.
.NET 7, SignalR ile, Blazor WebAssemblyJavaScript istemcisi ve SignalR için KestrelHTTP/2 desteği üzerinden WebSockets'i kullanıma sunar.
Not
HTTP/2 WebSockets GET yerine CONNECT isteklerini kullanır, bu nedenle kendi yollarınızın ve denetleyicilerinizin güncelleştirilmesi gerekebilir. Daha fazla bilgi için bu makaledeki Mevcut denetleyiciler için HTTP/2 WebSockets desteği ekleme konusuna bakın.
Chrome ve Edge'de HTTP/2 WebSockets varsayılan olarak etkindir ve bunu bayrağıyla birlikte network.http.spdy.websockets
sayfadaki FireFox'ta about:config
etkinleştirebilirsiniz.
WebSockets başlangıçta HTTP/1.1 için tasarlanmıştır ancak o zamandan beri HTTP/2 üzerinde çalışacak şekilde uyarlanmıştır. (RFC 8441)
SignalR
ASP.NET Core SignalR , uygulamalara gerçek zamanlı web işlevselliği eklemeyi kolaylaştıran bir kitaplıktır. Mümkün olduğunda WebSockets kullanır.
Çoğu uygulama için ham WebSockets yerine önerilir SignalR . SignalR:
- WebSockets'in kullanılamadığı ortamlar için aktarım geri dönüşünü sağlar.
- Temel bir uzaktan yordam çağrısı uygulama modeli sağlar.
- Çoğu senaryoda ham WebSockets kullanımıyla karşılaştırıldığında önemli bir performans dezavantajı yoktur.
HTTP/2 üzerinden WebSockets aşağıdakiler için desteklenir:
- ASP.NET Core SignalR JavaScript istemcisi
- ile ASP.NET Core SignalRBlazor WebAssembly
Bazı uygulamalar için.NET üzerindeki gRPC, WebSockets'e bir alternatif sağlar.
Önkoşullar
- ASP.NET Core'u destekleyen tüm işletim sistemi:
- Windows 7 / Windows Server 2008 veya üzeri
- Linux
- macOS
- Uygulama IIS ile Windows üzerinde çalışıyorsa:
- Windows 8 / Windows Server 2012 veya üzeri
- IIS 8 / IIS 8 Express
- WebSockets etkinleştirilmelidir. IIS/IIS Express desteği bölümüne bakın.
- Uygulama HTTP.sys üzerinde çalışıyorsa:
- Windows 8 / Windows Server 2012 veya üzeri
- Desteklenen tarayıcılar için bkz . Kullanabilir miyim?
Ara yazılımı yapılandırma
içinde WebSockets ara yazılımını Program.cs
ekleyin:
app.UseWebSockets();
Aşağıdaki ayarlar yapılandırılabilir:
- KeepAliveInterval - Proxy'lerin bağlantıyı açık tutmasını sağlamak için istemciye "ping" çerçeveleri gönderme sıklığı. Varsayılan değer iki dakikadır.
- AllowedOrigins - WebSocket istekleri için izin verilen Kaynak üst bilgi değerlerinin listesi. Varsayılan olarak tüm çıkış noktalarına izin verilir. Daha fazla bilgi için bu makaledeki WebSocket kaynak kısıtlaması bölümüne bakın.
var webSocketOptions = new WebSocketOptions
{
KeepAliveInterval = TimeSpan.FromMinutes(2)
};
app.UseWebSockets(webSocketOptions);
WebSocket isteklerini kabul etme
İstek yaşam döngüsünün sonraki bölümlerinde (örneğin, daha sonraki bir işlem yönteminde Program.cs
) bunun bir WebSocket isteği olup olmadığını denetleyin ve WebSocket isteğini kabul edin.
Aşağıdaki örnek, içinde daha sonra verilmiştir Program.cs
:
app.Use(async (context, next) =>
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
await Echo(webSocket);
}
else
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}
else
{
await next(context);
}
});
WebSocket isteği herhangi bir URL'de gelebilir, ancak bu örnek kod yalnızca için /ws
istekleri kabul eder.
Benzer bir yaklaşım bir denetleyici yönteminde de ele alınabilir:
public class WebSocketController : ControllerBase
{
[Route("/ws")]
public async Task Get()
{
if (HttpContext.WebSockets.IsWebSocketRequest)
{
using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
await Echo(webSocket);
}
else
{
HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}
WebSocket kullanırken, bağlantı süresi boyunca ara yazılım işlem hattını çalışır durumda tutmanız gerekir . Ara yazılım işlem hattı sona erdikten sonra WebSocket iletisi göndermeye veya almaya çalışırsanız, aşağıdaki gibi bir özel durumla karşılaşabilirsiniz:
System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake. ---> System.ObjectDisposedException: Cannot write to the response body, the response has completed.
Object name: 'HttpResponseStream'.
WebSocket'e veri yazmak için arka plan hizmeti kullanıyorsanız ara yazılım işlem hattını çalışır durumda tuttuğunuzdan emin olun. Bunu bir TaskCompletionSource<TResult>kullanarak yapın. TaskCompletionSource
öğesini arka plan hizmetinize geçirin ve WebSocket ile bitirdiğinizde aramasını TrySetResult sağlayın. Task Ardındanawait
, aşağıdaki örnekte gösterildiği gibi istek sırasında özelliği:
app.Run(async (context) =>
{
using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
var socketFinishedTcs = new TaskCompletionSource<object>();
BackgroundSocketProcessor.AddSocket(webSocket, socketFinishedTcs);
await socketFinishedTcs.Task;
});
WebSocket kapalı özel durumu, bir eylem yönteminden çok erken geri dönerken de oluşabilir. Eylem yönteminde yuva kabul ederken, eylem yönteminden dönmeden önce yuvayı kullanan kodun tamamlanmasını bekleyin.
Önemli iş parçacığı sorunlarına neden olabileceğinden, yuvanın tamamlanmasını beklemek için hiçbir zaman , Task.Result
veya benzer engelleme çağrıları kullanmayınTask.Wait
. Her zaman kullanın await
.
Mevcut denetleyiciler için HTTP/2 WebSockets desteği ekleme
.NET 7, SignalR ile, Blazor WebAssemblyJavaScript istemcisi ve SignalR için KestrelHTTP/2 desteği üzerinden WebSockets'i kullanıma sunar. HTTP/2 WebSockets GET yerine CONNECT isteklerini kullanır. Daha önce Websocket istekleri için denetleyici eylem yönteminizde kullandıysanız [HttpGet("/path")]
, bunu kullanmak [Route("/path")]
üzere güncelleştirin.
public class WebSocketController : ControllerBase
{
[Route("/ws")]
public async Task Get()
{
if (HttpContext.WebSockets.IsWebSocketRequest)
{
using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
await Echo(webSocket);
}
else
{
HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}
Sıkıştırma
Uyarı
Şifrelenmiş bağlantılar üzerinden sıkıştırmanın etkinleştirilmesi, bir uygulamanın /BREACH saldırılara CRIMEtabi olmasını sağlayabilir.
Hassas bilgiler gönderiyorsanız, sıkıştırmayı etkinleştirmekten veya çağrısı WebSocket.SendAsync
yaparken kullanmaktan WebSocketMessageFlags.DisableCompression
kaçının.
Bu, WebSocket'in her iki tarafı için de geçerlidir. Tarayıcıdaki WebSockets API'sinin gönderme başına sıkıştırmayı devre dışı bırakmak için yapılandırması olmadığını unutmayın.
İletilerin WebSockets üzerinden sıkıştırması isteniyorsa, kabul kodu aşağıdaki gibi sıkıştırmaya izin verdiği belirtmelidir:
using (var webSocket = await context.WebSockets.AcceptWebSocketAsync(
new WebSocketAcceptContext { DangerousEnableCompression = true }))
{
}
WebSocketAcceptContext.ServerMaxWindowBits
ve WebSocketAcceptContext.DisableServerContextTakeover
sıkıştırmanın nasıl çalıştığını denetleen gelişmiş seçeneklerdir.
İlk bağlantı kurulurken istemci ile sunucu arasında sıkıştırma anlaşması yapılır. Anlaşma hakkında daha fazla bilgi için bkz. WebSocket RFC için Sıkıştırma Uzantıları.
Not
Sıkıştırma anlaşması sunucu veya istemci tarafından kabul edilirse, bağlantı yine de kurulur. Ancak, bağlantı iletileri gönderirken ve alırken sıkıştırma kullanmaz.
İleti alma ve gönderme
yöntemi TCP AcceptWebSocketAsync
bağlantısını bir WebSocket bağlantısına yükselterek bir WebSocket nesne sağlar. WebSocket
İleti göndermek ve almak için nesnesini kullanın.
WebSocket isteğini kabul eden daha önce gösterilen kod, nesnesini bir Echo
yönteme geçirirWebSocket
. Kod bir ileti alır ve hemen aynı iletiyi geri gönderir. İstemci bağlantıyı kapatana kadar iletiler bir döngü içinde gönderilir ve alınır:
private static async Task Echo(WebSocket webSocket)
{
var buffer = new byte[1024 * 4];
var receiveResult = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);
while (!receiveResult.CloseStatus.HasValue)
{
await webSocket.SendAsync(
new ArraySegment<byte>(buffer, 0, receiveResult.Count),
receiveResult.MessageType,
receiveResult.EndOfMessage,
CancellationToken.None);
receiveResult = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);
}
await webSocket.CloseAsync(
receiveResult.CloseStatus.Value,
receiveResult.CloseStatusDescription,
CancellationToken.None);
}
Döngüye başlamadan önce WebSocket bağlantısını kabul ederken ara yazılım işlem hattı sona erer. Yuva kapatılmaya devam ettikten sonra işlem hattı gevşer. Başka bir ifadeyle, WebSocket kabul edildiğinde istek işlem hattında ilerlemeyi durdurur. Döngü tamamlandığında ve yuva kapatıldığında istek işlem hattını yedekler.
İstemci bağlantısının kesilmesini işleme
Bağlantı kaybı nedeniyle istemcinin bağlantısı kesildiğinde sunucu otomatik olarak bilgilendirilir. Sunucu yalnızca istemci gönderirse bir bağlantı kesme iletisi alır ve bu işlem İnternet bağlantısı kesilirse yapılamaz. Böyle bir durumda işlem yapmak istiyorsanız, istemciden belirli bir zaman penceresi içinde hiçbir şey alınmadığında bir zaman aşımı ayarlayın.
İstemci her zaman ileti göndermiyorsa ve bağlantı boşta olduğu için zaman aşımına uğradıysanız, istemcinin her X saniyede bir ping iletisi göndermek için zamanlayıcı kullanmasını sağlayın. Sunucuda, bir ileti öncekinden sonraki 2*X saniye içinde gelmediyse bağlantıyı sonlandırın ve istemcinin bağlantısının kesildiğini bildirin. Ping iletisini tutabilecek ağ gecikmelerinde fazladan süre bırakmak için beklenen zaman aralığının iki katı kadar bekleyin.
WebSocket kaynak kısıtlaması
CORS tarafından sağlanan korumalar WebSockets için geçerli değildir. Tarayıcılar aşağıdakileri yapmaz:
- CORS uçuş öncesi istekleri gerçekleştirin.
- WebSocket istekleri yaparken üst bilgilerde
Access-Control
belirtilen kısıtlamalara uyun.
Ancak tarayıcılar WebSocket istekleri gönderirken üst bilgiyi gönderir Origin
. Uygulamalar, yalnızca beklenen kaynaklardan gelen WebSockets'e izin verildiğinden emin olmak için bu üst bilgileri doğrulayacak şekilde yapılandırılmalıdır.
Sunucunuzu "https://server.com" ve istemcinizi "https://client.com", "https://client.com" webSockets'in AllowedOrigins doğrulanması için listeye gidin.
var webSocketOptions = new WebSocketOptions
{
KeepAliveInterval = TimeSpan.FromMinutes(2)
};
webSocketOptions.AllowedOrigins.Add("https://client.com");
webSocketOptions.AllowedOrigins.Add("https://www.client.com");
app.UseWebSockets(webSocketOptions);
Not
Üst Origin
bilgi istemci tarafından denetlenebilir ve üst bilgi gibi Referer
sahte olabilir. Bu üst bilgileri kimlik doğrulama mekanizması olarak kullanmayın.
IIS/IIS Express desteği
Windows Server 2012 veya sonraki sürümleri ve IIS/IIS Express 8 veya üzeri yüklü Windows 8 veya sonraki sürümlerin WebSocket protokolü desteği vardır, ancak HTTP/2 üzerinden WebSockets için desteklenmez.
Not
WebSockets, IIS Express kullanılırken her zaman etkinleştirilir.
IIS'de WebSockets'i etkinleştirme
Windows Server 2012 veya sonraki sürümlerde WebSocket protokolü desteğini etkinleştirmek için:
Not
IIS Express kullanılırken bu adımlar gerekli değildir
- Yönet menüsünden Rol ve Özellik Ekle sihirbazını veya Sunucu Yöneticisi'ndeki bağlantıyı kullanın.
- Rol Tabanlı veya Özellik Tabanlı Yükleme'yi seçin. İleri'yi seçin.
- Uygun sunucuyu seçin (yerel sunucu varsayılan olarak seçilidir). İleri'yi seçin.
- Roller ağacında Web Sunucusu'nu (IIS) genişletin, Web Sunucusu'nu genişletin ve ardından Uygulama Geliştirme'yi genişletin.
- WebSocket Protokolü'ne tıklayın. İleri'yi seçin.
- Ek özellikler gerekmiyorsa İleri'yi seçin.
- Yükle'yi seçin.
- Yükleme tamamlandığında, sihirbazdan çıkmak için Kapat'ı seçin.
Windows 8 veya sonraki sürümlerde WebSocket protokolü desteğini etkinleştirmek için:
Not
IIS Express kullanılırken bu adımlar gerekli değildir
- Denetim Masası>Programlar>Programlar ve Özellikler> gidinWindows özelliklerini aç veya kapat seçeneğine gidin (ekranın sol tarafında).
- Şu düğümleri açın: Internet Information Services>World Wide Web Services>Uygulama Geliştirme Özellikleri.
- WebSocket Protokolü özelliğini seçin. Tamam'ı seçin.
Node'da socket.io kullanırken WebSocket'i devre dışı bırakın.js
Node. üzerindeki socket.io WebSocket desteğini kullanıyorsanız, web.configjs veya applicationHost.config içindeki öğesini kullanarak webSocket
varsayılan IIS WebSocket modülünü devre dışı bırakın. Bu adım gerçekleştirilmezse, IIS WebSocket modülü Node yerine WebSocket iletişimini işlemeye çalışır.js ve uygulamayı seçin.
<system.webServer>
<webSocket enabled="false" />
</system.webServer>
Örnek uygulama
Bu makaleye eşlik eden örnek uygulama bir yankı uygulamasıdır. WebSocket bağlantılarını yapan bir web sayfası vardır ve sunucu aldığı tüm iletileri istemciye yeniden gönderir. Örnek uygulama, hedeflenen .NET 7 veya üzeri bir çerçeve kullanılırken HTTP/2 üzerinden WebSockets'i destekler.
Uygulamayı çalıştırın:
- Uygulamayı Visual Studio'da çalıştırmak için: Örnek projeyi Visual Studio'da açın ve hata ayıklayıcı olmadan çalıştırmak için Ctrl+F5 tuşlarına basın.
- Uygulamayı komut kabuğunda çalıştırmak için: komutunu
dotnet run
çalıştırın ve tarayıcıda adresinehttp://localhost:<port>
gidin.
Web sayfası bağlantı durumunu gösterir:
Gösterilen URL'ye WebSocket isteği göndermek için Bağlan'ı seçin. Bir test iletisi girin ve Gönder'i seçin. İşiniz bittiğinde Yuvayı Kapat'ı seçin. İletişim Günlüğü bölümü, her bir açma, gönderme ve kapatma eylemini olduğu gibi bildirir.
Bu makalede, ASP.NET Core'da WebSockets ile çalışmaya başlama açıklanmaktadır. WebSocket (RFC 6455), TCP bağlantıları üzerinden iki yönlü kalıcı iletişim kanalları sağlayan bir protokoldür. Sohbet, pano ve oyun uygulamaları gibi hızlı, gerçek zamanlı iletişimden yararlanan uygulamalarda kullanılır.
Örnek kodu görüntüleme veya indirme (indirme, çalıştırma).
Http/2 WebSockets desteği
HTTP/2 üzerinden WebSockets kullanmak aşağıdaki gibi yeni özelliklerden yararlanır:
- Üst bilgi sıkıştırma.
- Sunucuya birden çok istekte bulunurken gereken süreyi ve kaynakları azaltan çoğullama.
Bu desteklenen özellikler tüm HTTP/2 özellikli platformlarda Kestrel kullanılabilir. Sürüm anlaşması tarayıcılarda ve Kestrel'de otomatiktir, bu nedenle yeni API'ler gerekmez.
.NET 7, SignalR ile, Blazor WebAssemblyJavaScript istemcisi ve SignalR için KestrelHTTP/2 desteği üzerinden WebSockets'i kullanıma sunar.
Not
HTTP/2 WebSockets GET yerine CONNECT isteklerini kullanır, bu nedenle kendi yollarınızın ve denetleyicilerinizin güncelleştirilmesi gerekebilir. Daha fazla bilgi için bu makaledeki Mevcut denetleyiciler için HTTP/2 WebSockets desteği ekleme konusuna bakın.
Chrome ve Edge'de HTTP/2 WebSockets varsayılan olarak etkindir ve bunu bayrağıyla birlikte network.http.spdy.websockets
sayfadaki FireFox'ta about:config
etkinleştirebilirsiniz.
WebSockets başlangıçta HTTP/1.1 için tasarlanmıştır ancak o zamandan beri HTTP/2 üzerinde çalışacak şekilde uyarlanmıştır. (RFC 8441)
SignalR
ASP.NET Core SignalR , uygulamalara gerçek zamanlı web işlevselliği eklemeyi kolaylaştıran bir kitaplıktır. Mümkün olduğunda WebSockets kullanır.
Çoğu uygulama için ham WebSockets yerine önerilir SignalR . SignalR:
- WebSockets'in kullanılamadığı ortamlar için aktarım geri dönüşünü sağlar.
- Temel bir uzaktan yordam çağrısı uygulama modeli sağlar.
- Çoğu senaryoda ham WebSockets kullanımıyla karşılaştırıldığında önemli bir performans dezavantajı yoktur.
HTTP/2 üzerinden WebSockets aşağıdakiler için desteklenir:
- ASP.NET Core SignalR JavaScript istemcisi
- ile ASP.NET Core SignalRBlazor WebAssembly
Bazı uygulamalar için.NET üzerindeki gRPC, WebSockets'e bir alternatif sağlar.
Önkoşullar
- ASP.NET Core'u destekleyen tüm işletim sistemi:
- Windows 7 / Windows Server 2008 veya üzeri
- Linux
- macOS
- Uygulama IIS ile Windows üzerinde çalışıyorsa:
- Windows 8 / Windows Server 2012 veya üzeri
- IIS 8 / IIS 8 Express
- WebSockets etkinleştirilmelidir. IIS/IIS Express desteği bölümüne bakın.
- Uygulama HTTP.sys üzerinde çalışıyorsa:
- Windows 8 / Windows Server 2012 veya üzeri
- Desteklenen tarayıcılar için bkz . Kullanabilir miyim?
Ara yazılımı yapılandırma
içinde WebSockets ara yazılımını Program.cs
ekleyin:
app.UseWebSockets();
Aşağıdaki ayarlar yapılandırılabilir:
- KeepAliveInterval - Proxy'lerin bağlantıyı açık tutmasını sağlamak için istemciye "ping" çerçeveleri gönderme sıklığı. Varsayılan değer iki dakikadır.
- AllowedOrigins - WebSocket istekleri için izin verilen Kaynak üst bilgi değerlerinin listesi. Varsayılan olarak tüm çıkış noktalarına izin verilir. Daha fazla bilgi için bu makaledeki WebSocket kaynak kısıtlaması bölümüne bakın.
var webSocketOptions = new WebSocketOptions
{
KeepAliveInterval = TimeSpan.FromMinutes(2)
};
app.UseWebSockets(webSocketOptions);
WebSocket isteklerini kabul etme
İstek yaşam döngüsünün sonraki bölümlerinde (örneğin, daha sonraki bir işlem yönteminde Program.cs
) bunun bir WebSocket isteği olup olmadığını denetleyin ve WebSocket isteğini kabul edin.
Aşağıdaki örnek, içinde daha sonra verilmiştir Program.cs
:
app.Use(async (context, next) =>
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
await Echo(webSocket);
}
else
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}
else
{
await next(context);
}
});
WebSocket isteği herhangi bir URL'de gelebilir, ancak bu örnek kod yalnızca için /ws
istekleri kabul eder.
Benzer bir yaklaşım bir denetleyici yönteminde de ele alınabilir:
public class WebSocketController : ControllerBase
{
[Route("/ws")]
public async Task Get()
{
if (HttpContext.WebSockets.IsWebSocketRequest)
{
using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
await Echo(webSocket);
}
else
{
HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}
WebSocket kullanırken, bağlantı süresi boyunca ara yazılım işlem hattını çalışır durumda tutmanız gerekir . Ara yazılım işlem hattı sona erdikten sonra WebSocket iletisi göndermeye veya almaya çalışırsanız, aşağıdaki gibi bir özel durumla karşılaşabilirsiniz:
System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake. ---> System.ObjectDisposedException: Cannot write to the response body, the response has completed.
Object name: 'HttpResponseStream'.
WebSocket'e veri yazmak için arka plan hizmeti kullanıyorsanız ara yazılım işlem hattını çalışır durumda tuttuğunuzdan emin olun. Bunu bir TaskCompletionSource<TResult>kullanarak yapın. TaskCompletionSource
öğesini arka plan hizmetinize geçirin ve WebSocket ile bitirdiğinizde aramasını TrySetResult sağlayın. Task Ardındanawait
, aşağıdaki örnekte gösterildiği gibi istek sırasında özelliği:
app.Run(async (context) =>
{
using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
var socketFinishedTcs = new TaskCompletionSource<object>();
BackgroundSocketProcessor.AddSocket(webSocket, socketFinishedTcs);
await socketFinishedTcs.Task;
});
WebSocket kapalı özel durumu, bir eylem yönteminden çok erken geri dönerken de oluşabilir. Eylem yönteminde yuva kabul ederken, eylem yönteminden dönmeden önce yuvayı kullanan kodun tamamlanmasını bekleyin.
Önemli iş parçacığı sorunlarına neden olabileceğinden, yuvanın tamamlanmasını beklemek için hiçbir zaman , Task.Result
veya benzer engelleme çağrıları kullanmayınTask.Wait
. Her zaman kullanın await
.
Mevcut denetleyiciler için HTTP/2 WebSockets desteği ekleme
.NET 7, SignalR ile, Blazor WebAssemblyJavaScript istemcisi ve SignalR için KestrelHTTP/2 desteği üzerinden WebSockets'i kullanıma sunar. HTTP/2 WebSockets GET yerine CONNECT isteklerini kullanır. Daha önce Websocket istekleri için denetleyici eylem yönteminizde kullandıysanız [HttpGet("/path")]
, bunu kullanmak [Route("/path")]
üzere güncelleştirin.
public class WebSocketController : ControllerBase
{
[Route("/ws")]
public async Task Get()
{
if (HttpContext.WebSockets.IsWebSocketRequest)
{
using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
await Echo(webSocket);
}
else
{
HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}
Sıkıştırma
Uyarı
Şifrelenmiş bağlantılar üzerinden sıkıştırmanın etkinleştirilmesi, bir uygulamanın /BREACH saldırılara CRIMEtabi olmasını sağlayabilir.
Hassas bilgiler gönderiyorsanız, sıkıştırmayı etkinleştirmekten veya çağrısı WebSocket.SendAsync
yaparken kullanmaktan WebSocketMessageFlags.DisableCompression
kaçının.
Bu, WebSocket'in her iki tarafı için de geçerlidir. Tarayıcıdaki WebSockets API'sinin gönderme başına sıkıştırmayı devre dışı bırakmak için yapılandırması olmadığını unutmayın.
İletilerin WebSockets üzerinden sıkıştırması isteniyorsa, kabul kodu aşağıdaki gibi sıkıştırmaya izin verdiği belirtmelidir:
using (var webSocket = await context.WebSockets.AcceptWebSocketAsync(
new WebSocketAcceptContext { DangerousEnableCompression = true }))
{
}
WebSocketAcceptContext.ServerMaxWindowBits
ve WebSocketAcceptContext.DisableServerContextTakeover
sıkıştırmanın nasıl çalıştığını denetleen gelişmiş seçeneklerdir.
İlk bağlantı kurulurken istemci ile sunucu arasında sıkıştırma anlaşması yapılır. Anlaşma hakkında daha fazla bilgi için bkz. WebSocket RFC için Sıkıştırma Uzantıları.
Not
Sıkıştırma anlaşması sunucu veya istemci tarafından kabul edilirse, bağlantı yine de kurulur. Ancak, bağlantı iletileri gönderirken ve alırken sıkıştırma kullanmaz.
İleti alma ve gönderme
yöntemi TCP AcceptWebSocketAsync
bağlantısını bir WebSocket bağlantısına yükselterek bir WebSocket nesne sağlar. WebSocket
İleti göndermek ve almak için nesnesini kullanın.
WebSocket isteğini kabul eden daha önce gösterilen kod, nesnesini bir Echo
yönteme geçirirWebSocket
. Kod bir ileti alır ve hemen aynı iletiyi geri gönderir. İstemci bağlantıyı kapatana kadar iletiler bir döngü içinde gönderilir ve alınır:
private static async Task Echo(WebSocket webSocket)
{
var buffer = new byte[1024 * 4];
var receiveResult = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);
while (!receiveResult.CloseStatus.HasValue)
{
await webSocket.SendAsync(
new ArraySegment<byte>(buffer, 0, receiveResult.Count),
receiveResult.MessageType,
receiveResult.EndOfMessage,
CancellationToken.None);
receiveResult = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);
}
await webSocket.CloseAsync(
receiveResult.CloseStatus.Value,
receiveResult.CloseStatusDescription,
CancellationToken.None);
}
Döngüye başlamadan önce WebSocket bağlantısını kabul ederken ara yazılım işlem hattı sona erer. Yuva kapatılmaya devam ettikten sonra işlem hattı gevşer. Başka bir ifadeyle, WebSocket kabul edildiğinde istek işlem hattında ilerlemeyi durdurur. Döngü tamamlandığında ve yuva kapatıldığında istek işlem hattını yedekler.
İstemci bağlantısının kesilmesini işleme
Bağlantı kaybı nedeniyle istemcinin bağlantısı kesildiğinde sunucu otomatik olarak bilgilendirilir. Sunucu yalnızca istemci gönderirse bir bağlantı kesme iletisi alır ve bu işlem İnternet bağlantısı kesilirse yapılamaz. Böyle bir durumda işlem yapmak istiyorsanız, istemciden belirli bir zaman penceresi içinde hiçbir şey alınmadığında bir zaman aşımı ayarlayın.
İstemci her zaman ileti göndermiyorsa ve bağlantı boşta olduğu için zaman aşımına uğradıysanız, istemcinin her X saniyede bir ping iletisi göndermek için zamanlayıcı kullanmasını sağlayın. Sunucuda, bir ileti öncekinden sonraki 2*X saniye içinde gelmediyse bağlantıyı sonlandırın ve istemcinin bağlantısının kesildiğini bildirin. Ping iletisini tutabilecek ağ gecikmelerinde fazladan süre bırakmak için beklenen zaman aralığının iki katı kadar bekleyin.
WebSocket kaynak kısıtlaması
CORS tarafından sağlanan korumalar WebSockets için geçerli değildir. Tarayıcılar aşağıdakileri yapmaz:
- CORS uçuş öncesi istekleri gerçekleştirin.
- WebSocket istekleri yaparken üst bilgilerde
Access-Control
belirtilen kısıtlamalara uyun.
Ancak tarayıcılar WebSocket istekleri gönderirken üst bilgiyi gönderir Origin
. Uygulamalar, yalnızca beklenen kaynaklardan gelen WebSockets'e izin verildiğinden emin olmak için bu üst bilgileri doğrulayacak şekilde yapılandırılmalıdır.
Sunucunuzu "https://server.com" ve istemcinizi "https://client.com", "https://client.com" webSockets'in AllowedOrigins doğrulanması için listeye gidin.
var webSocketOptions = new WebSocketOptions
{
KeepAliveInterval = TimeSpan.FromMinutes(2)
};
webSocketOptions.AllowedOrigins.Add("https://client.com");
webSocketOptions.AllowedOrigins.Add("https://www.client.com");
app.UseWebSockets(webSocketOptions);
Not
Üst Origin
bilgi istemci tarafından denetlenebilir ve üst bilgi gibi Referer
sahte olabilir. Bu üst bilgileri kimlik doğrulama mekanizması olarak kullanmayın.
IIS/IIS Express desteği
Windows Server 2012 veya sonraki sürümleri ve IIS/IIS Express 8 veya üzeri yüklü Windows 8 veya sonraki sürümlerin WebSocket protokolü desteği vardır, ancak HTTP/2 üzerinden WebSockets için desteklenmez.
Not
WebSockets, IIS Express kullanılırken her zaman etkinleştirilir.
IIS'de WebSockets'i etkinleştirme
Windows Server 2012 veya sonraki sürümlerde WebSocket protokolü desteğini etkinleştirmek için:
Not
IIS Express kullanılırken bu adımlar gerekli değildir
- Yönet menüsünden Rol ve Özellik Ekle sihirbazını veya Sunucu Yöneticisi'ndeki bağlantıyı kullanın.
- Rol Tabanlı veya Özellik Tabanlı Yükleme'yi seçin. İleri'yi seçin.
- Uygun sunucuyu seçin (yerel sunucu varsayılan olarak seçilidir). İleri'yi seçin.
- Roller ağacında Web Sunucusu'nu (IIS) genişletin, Web Sunucusu'nu genişletin ve ardından Uygulama Geliştirme'yi genişletin.
- WebSocket Protokolü'ne tıklayın. İleri'yi seçin.
- Ek özellikler gerekmiyorsa İleri'yi seçin.
- Yükle'yi seçin.
- Yükleme tamamlandığında, sihirbazdan çıkmak için Kapat'ı seçin.
Windows 8 veya sonraki sürümlerde WebSocket protokolü desteğini etkinleştirmek için:
Not
IIS Express kullanılırken bu adımlar gerekli değildir
- Denetim Masası>Programlar>Programlar ve Özellikler> gidinWindows özelliklerini aç veya kapat seçeneğine gidin (ekranın sol tarafında).
- Şu düğümleri açın: Internet Information Services>World Wide Web Services>Uygulama Geliştirme Özellikleri.
- WebSocket Protokolü özelliğini seçin. Tamam'ı seçin.
Node'da socket.io kullanırken WebSocket'i devre dışı bırakın.js
Node. üzerindeki socket.io WebSocket desteğini kullanıyorsanız, web.configjs veya applicationHost.config içindeki öğesini kullanarak webSocket
varsayılan IIS WebSocket modülünü devre dışı bırakın. Bu adım gerçekleştirilmezse, IIS WebSocket modülü Node yerine WebSocket iletişimini işlemeye çalışır.js ve uygulamayı seçin.
<system.webServer>
<webSocket enabled="false" />
</system.webServer>
Örnek uygulama
Bu makaleye eşlik eden örnek uygulama bir yankı uygulamasıdır. WebSocket bağlantılarını yapan bir web sayfası vardır ve sunucu aldığı tüm iletileri istemciye yeniden gönderir. Örnek uygulama, hedeflenen .NET 7 veya üzeri bir çerçeve kullanılırken HTTP/2 üzerinden WebSockets'i destekler.
Uygulamayı çalıştırın:
- Uygulamayı Visual Studio'da çalıştırmak için: Örnek projeyi Visual Studio'da açın ve hata ayıklayıcı olmadan çalıştırmak için Ctrl+F5 tuşlarına basın.
- Uygulamayı komut kabuğunda çalıştırmak için: komutunu
dotnet run
çalıştırın ve tarayıcıda adresinehttp://localhost:<port>
gidin.
Web sayfası bağlantı durumunu gösterir:
Gösterilen URL'ye WebSocket isteği göndermek için Bağlan'ı seçin. Bir test iletisi girin ve Gönder'i seçin. İşiniz bittiğinde Yuvayı Kapat'ı seçin. İletişim Günlüğü bölümü, her bir açma, gönderme ve kapatma eylemini olduğu gibi bildirir.
Bu makalede, ASP.NET Core'da WebSockets ile çalışmaya başlama açıklanmaktadır. WebSocket (RFC 6455), TCP bağlantıları üzerinden iki yönlü kalıcı iletişim kanalları sağlayan bir protokoldür. Sohbet, pano ve oyun uygulamaları gibi hızlı, gerçek zamanlı iletişimden yararlanan uygulamalarda kullanılır.
Örnek kodu görüntüleme veya indirme (indirme, çalıştırma).
SignalR
ASP.NET Core SignalR , uygulamalara gerçek zamanlı web işlevselliği eklemeyi kolaylaştıran bir kitaplıktır. Mümkün olduğunda WebSockets kullanır.
Çoğu uygulama için ham WebSockets üzerinden önerilir SignalR . SignalR WebSockets'in kullanılamadığı ortamlar için aktarım geri dönüşünü sağlar. Ayrıca temel bir uzaktan yordam çağrısı uygulama modeli sağlar. Çoğu senaryoda ham SignalR WebSockets kullanımına kıyasla önemli bir performans dezavantajı yoktur.
Bazı uygulamalar için.NET üzerindeki gRPC, WebSockets'e bir alternatif sağlar.
Önkoşullar
- ASP.NET Core'u destekleyen tüm işletim sistemi:
- Windows 7 / Windows Server 2008 veya üzeri
- Linux
- macOS
- Uygulama IIS ile Windows üzerinde çalışıyorsa:
- Windows 8 / Windows Server 2012 veya üzeri
- IIS 8 / IIS 8 Express
- WebSockets etkinleştirilmelidir. IIS/IIS Express desteği bölümüne bakın.
- Uygulama HTTP.sys üzerinde çalışıyorsa:
- Windows 8 / Windows Server 2012 veya üzeri
- Desteklenen tarayıcılar için bkz . Kullanabilir miyim?
Ara yazılımı yapılandırma
içinde WebSockets ara yazılımını Program.cs
ekleyin:
app.UseWebSockets();
Aşağıdaki ayarlar yapılandırılabilir:
- KeepAliveInterval - Proxy'lerin bağlantıyı açık tutmasını sağlamak için istemciye "ping" çerçeveleri gönderme sıklığı. Varsayılan değer iki dakikadır.
- AllowedOrigins - WebSocket istekleri için izin verilen Kaynak üst bilgi değerlerinin listesi. Varsayılan olarak tüm çıkış noktalarına izin verilir. Daha fazla bilgi için bu makaledeki WebSocket kaynak kısıtlaması bölümüne bakın.
var webSocketOptions = new WebSocketOptions
{
KeepAliveInterval = TimeSpan.FromMinutes(2)
};
app.UseWebSockets(webSocketOptions);
WebSocket isteklerini kabul etme
İstek yaşam döngüsünün sonraki bölümlerinde (örneğin, daha sonraki bir işlem yönteminde Program.cs
) bunun bir WebSocket isteği olup olmadığını denetleyin ve WebSocket isteğini kabul edin.
Aşağıdaki örnek, içinde daha sonra verilmiştir Program.cs
:
app.Use(async (context, next) =>
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
await Echo(webSocket);
}
else
{
context.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}
else
{
await next(context);
}
});
WebSocket isteği herhangi bir URL'de gelebilir, ancak bu örnek kod yalnızca için /ws
istekleri kabul eder.
Benzer bir yaklaşım bir denetleyici yönteminde de ele alınabilir:
public class WebSocketController : ControllerBase
{
[HttpGet("/ws")]
public async Task Get()
{
if (HttpContext.WebSockets.IsWebSocketRequest)
{
using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
await Echo(webSocket);
}
else
{
HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}
WebSocket kullanırken, bağlantı süresi boyunca ara yazılım işlem hattını çalışır durumda tutmanız gerekir . Ara yazılım işlem hattı sona erdikten sonra WebSocket iletisi göndermeye veya almaya çalışırsanız, aşağıdaki gibi bir özel durumla karşılaşabilirsiniz:
System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake. ---> System.ObjectDisposedException: Cannot write to the response body, the response has completed.
Object name: 'HttpResponseStream'.
WebSocket'e veri yazmak için arka plan hizmeti kullanıyorsanız ara yazılım işlem hattını çalışır durumda tuttuğunuzdan emin olun. Bunu bir TaskCompletionSource<TResult>kullanarak yapın. TaskCompletionSource
öğesini arka plan hizmetinize geçirin ve WebSocket ile bitirdiğinizde aramasını TrySetResult sağlayın. Task Ardındanawait
, aşağıdaki örnekte gösterildiği gibi istek sırasında özelliği:
app.Run(async (context) =>
{
using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
var socketFinishedTcs = new TaskCompletionSource<object>();
BackgroundSocketProcessor.AddSocket(webSocket, socketFinishedTcs);
await socketFinishedTcs.Task;
});
WebSocket kapalı özel durumu, bir eylem yönteminden çok erken geri dönerken de oluşabilir. Eylem yönteminde yuva kabul ederken, eylem yönteminden dönmeden önce yuvayı kullanan kodun tamamlanmasını bekleyin.
Önemli iş parçacığı sorunlarına neden olabileceğinden, yuvanın tamamlanmasını beklemek için hiçbir zaman , Task.Result
veya benzer engelleme çağrıları kullanmayınTask.Wait
. Her zaman kullanın await
.
Sıkıştırma
Uyarı
Şifrelenmiş bağlantılar üzerinden sıkıştırmanın etkinleştirilmesi, bir uygulamanın /BREACH saldırılara CRIMEtabi olmasını sağlayabilir.
Hassas bilgiler gönderiyorsanız, sıkıştırmayı etkinleştirmekten veya çağrısı WebSocket.SendAsync
yaparken kullanmaktan WebSocketMessageFlags.DisableCompression
kaçının.
Bu, WebSocket'in her iki tarafı için de geçerlidir. Tarayıcıdaki WebSockets API'sinin gönderme başına sıkıştırmayı devre dışı bırakmak için yapılandırması olmadığını unutmayın.
İletilerin WebSockets üzerinden sıkıştırması isteniyorsa, kabul kodu aşağıdaki gibi sıkıştırmaya izin verdiği belirtmelidir:
using (var webSocket = await context.WebSockets.AcceptWebSocketAsync(
new WebSocketAcceptContext { DangerousEnableCompression = true }))
{
}
WebSocketAcceptContext.ServerMaxWindowBits
ve WebSocketAcceptContext.DisableServerContextTakeover
sıkıştırmanın nasıl çalıştığını denetleen gelişmiş seçeneklerdir.
İlk bağlantı kurulurken istemci ile sunucu arasında sıkıştırma anlaşması yapılır. Anlaşma hakkında daha fazla bilgi için bkz. WebSocket RFC için Sıkıştırma Uzantıları.
Not
Sıkıştırma anlaşması sunucu veya istemci tarafından kabul edilirse, bağlantı yine de kurulur. Ancak, bağlantı iletileri gönderirken ve alırken sıkıştırma kullanmaz.
İleti alma ve gönderme
yöntemi TCP AcceptWebSocketAsync
bağlantısını bir WebSocket bağlantısına yükselterek bir WebSocket nesne sağlar. WebSocket
İleti göndermek ve almak için nesnesini kullanın.
WebSocket isteğini kabul eden daha önce gösterilen kod, nesnesini bir Echo
yönteme geçirirWebSocket
. Kod bir ileti alır ve hemen aynı iletiyi geri gönderir. İstemci bağlantıyı kapatana kadar iletiler bir döngü içinde gönderilir ve alınır:
private static async Task Echo(WebSocket webSocket)
{
var buffer = new byte[1024 * 4];
var receiveResult = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);
while (!receiveResult.CloseStatus.HasValue)
{
await webSocket.SendAsync(
new ArraySegment<byte>(buffer, 0, receiveResult.Count),
receiveResult.MessageType,
receiveResult.EndOfMessage,
CancellationToken.None);
receiveResult = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);
}
await webSocket.CloseAsync(
receiveResult.CloseStatus.Value,
receiveResult.CloseStatusDescription,
CancellationToken.None);
}
Döngüye başlamadan önce WebSocket bağlantısını kabul ederken ara yazılım işlem hattı sona erer. Yuva kapatılmaya devam ettikten sonra işlem hattı gevşer. Başka bir ifadeyle, WebSocket kabul edildiğinde istek işlem hattında ilerlemeyi durdurur. Döngü tamamlandığında ve yuva kapatıldığında istek işlem hattını yedekler.
İstemci bağlantısının kesilmesini işleme
Bağlantı kaybı nedeniyle istemcinin bağlantısı kesildiğinde sunucu otomatik olarak bilgilendirilir. Sunucu yalnızca istemci gönderirse bir bağlantı kesme iletisi alır ve bu işlem İnternet bağlantısı kesilirse yapılamaz. Böyle bir durumda işlem yapmak istiyorsanız, istemciden belirli bir zaman penceresi içinde hiçbir şey alınmadığında bir zaman aşımı ayarlayın.
İstemci her zaman ileti göndermiyorsa ve bağlantı boşta olduğu için zaman aşımına uğradıysanız, istemcinin her X saniyede bir ping iletisi göndermek için zamanlayıcı kullanmasını sağlayın. Sunucuda, bir ileti öncekinden sonraki 2*X saniye içinde gelmediyse bağlantıyı sonlandırın ve istemcinin bağlantısının kesildiğini bildirin. Ping iletisini tutabilecek ağ gecikmelerinde fazladan süre bırakmak için beklenen zaman aralığının iki katı kadar bekleyin.
WebSocket kaynak kısıtlaması
CORS tarafından sağlanan korumalar WebSockets için geçerli değildir. Tarayıcılar aşağıdakileri yapmaz:
- CORS uçuş öncesi istekleri gerçekleştirin.
- WebSocket istekleri yaparken üst bilgilerde
Access-Control
belirtilen kısıtlamalara uyun.
Ancak tarayıcılar WebSocket istekleri gönderirken üst bilgiyi gönderir Origin
. Uygulamalar, yalnızca beklenen kaynaklardan gelen WebSockets'e izin verildiğinden emin olmak için bu üst bilgileri doğrulayacak şekilde yapılandırılmalıdır.
Sunucunuzu "https://server.com" ve istemcinizi "https://client.com", "https://client.com" webSockets'in AllowedOrigins doğrulanması için listeye gidin.
var webSocketOptions = new WebSocketOptions
{
KeepAliveInterval = TimeSpan.FromMinutes(2)
};
webSocketOptions.AllowedOrigins.Add("https://client.com");
webSocketOptions.AllowedOrigins.Add("https://www.client.com");
app.UseWebSockets(webSocketOptions);
Not
Üst Origin
bilgi istemci tarafından denetlenebilir ve üst bilgi gibi Referer
sahte olabilir. Bu üst bilgileri kimlik doğrulama mekanizması olarak kullanmayın.
IIS/IIS Express desteği
Windows Server 2012 veya üzeri ve IIS/IIS Express 8 veya üzeri yüklü Windows 8 veya üzeri, WebSocket protokolü desteğine sahiptir.
Not
WebSockets, IIS Express kullanılırken her zaman etkinleştirilir.
IIS'de WebSockets'i etkinleştirme
Windows Server 2012 veya sonraki sürümlerde WebSocket protokolü desteğini etkinleştirmek için:
Not
IIS Express kullanılırken bu adımlar gerekli değildir
- Yönet menüsünden Rol ve Özellik Ekle sihirbazını veya Sunucu Yöneticisi'ndeki bağlantıyı kullanın.
- Rol Tabanlı veya Özellik Tabanlı Yükleme'yi seçin. İleri'yi seçin.
- Uygun sunucuyu seçin (yerel sunucu varsayılan olarak seçilidir). İleri'yi seçin.
- Roller ağacında Web Sunucusu'nu (IIS) genişletin, Web Sunucusu'nu genişletin ve ardından Uygulama Geliştirme'yi genişletin.
- WebSocket Protokolü'ne tıklayın. İleri'yi seçin.
- Ek özellikler gerekmiyorsa İleri'yi seçin.
- Yükle'yi seçin.
- Yükleme tamamlandığında, sihirbazdan çıkmak için Kapat'ı seçin.
Windows 8 veya sonraki sürümlerde WebSocket protokolü desteğini etkinleştirmek için:
Not
IIS Express kullanılırken bu adımlar gerekli değildir
- Denetim Masası>Programlar>Programlar ve Özellikler> gidinWindows özelliklerini aç veya kapat seçeneğine gidin (ekranın sol tarafında).
- Şu düğümleri açın: Internet Information Services>World Wide Web Services>Uygulama Geliştirme Özellikleri.
- WebSocket Protokolü özelliğini seçin. Tamam'ı seçin.
Node'da socket.io kullanırken WebSocket'i devre dışı bırakın.js
Node. üzerindeki socket.io WebSocket desteğini kullanıyorsanız, web.configjs veya applicationHost.config içindeki öğesini kullanarak webSocket
varsayılan IIS WebSocket modülünü devre dışı bırakın. Bu adım gerçekleştirilmezse, IIS WebSocket modülü Node yerine WebSocket iletişimini işlemeye çalışır.js ve uygulamayı seçin.
<system.webServer>
<webSocket enabled="false" />
</system.webServer>
Örnek uygulama
Bu makaleye eşlik eden örnek uygulama bir yankı uygulamasıdır. WebSocket bağlantılarını yapan bir web sayfası vardır ve sunucu aldığı tüm iletileri istemciye yeniden gönderir. Örnek uygulama, IIS Express ile Visual Studio'dan çalıştırılacak şekilde yapılandırılmadığından, ile bir komut kabuğunda dotnet run
uygulamayı çalıştırın ve tarayıcıda öğesine http://localhost:<port>
gidin. Web sayfası bağlantı durumunu gösterir:
Gösterilen URL'ye WebSocket isteği göndermek için Bağlan'ı seçin. Bir test iletisi girin ve Gönder'i seçin. İşiniz bittiğinde Yuvayı Kapat'ı seçin. İletişim Günlüğü bölümü, her bir açma, gönderme ve kapatma eylemini olduğu gibi bildirir.
Bu makalede, ASP.NET Core'da WebSockets ile çalışmaya başlama açıklanmaktadır. WebSocket (RFC 6455), TCP bağlantıları üzerinden iki yönlü kalıcı iletişim kanalları sağlayan bir protokoldür. Sohbet, pano ve oyun uygulamaları gibi hızlı, gerçek zamanlı iletişimden yararlanan uygulamalarda kullanılır.
Örnek kodu görüntüleme veya indirme (indirme). Nasıl çalıştırılır?
SignalR
ASP.NET Core SignalR , uygulamalara gerçek zamanlı web işlevselliği eklemeyi kolaylaştıran bir kitaplıktır. Mümkün olduğunda WebSockets kullanır.
Çoğu uygulama için ham WebSockets üzerinden önerilir SignalR . SignalR WebSockets'in kullanılamadığı ortamlar için aktarım geri dönüşünü sağlar. Ayrıca temel bir uzaktan yordam çağrısı uygulama modeli sağlar. Çoğu senaryoda ham SignalR WebSockets kullanımına kıyasla önemli bir performans dezavantajı yoktur.
Bazı uygulamalar için.NET üzerindeki gRPC, WebSockets'e bir alternatif sağlar.
Önkoşullar
- ASP.NET Core'u destekleyen tüm işletim sistemi:
- Windows 7 / Windows Server 2008 veya üzeri
- Linux
- macOS
- Uygulama IIS ile Windows üzerinde çalışıyorsa:
- Windows 8 / Windows Server 2012 veya üzeri
- IIS 8 / IIS 8 Express
- WebSockets etkinleştirilmelidir. IIS/IIS Express desteği bölümüne bakın.
- Uygulama HTTP.sys üzerinde çalışıyorsa:
- Windows 8 / Windows Server 2012 veya üzeri
- Desteklenen tarayıcılar için bkz . Kullanabilir miyim?
Ara yazılımı yapılandırma
Sınıfının yöntemine Configure
Startup
WebSockets ara yazılımını ekleyin:
app.UseWebSockets();
Not
Bir denetleyicide WebSocket isteklerini kabul etmek istiyorsanız çağrısının app.UseWebSockets
öncesinde app.UseEndpoints
gerçekleşmesi gerekir.
Aşağıdaki ayarlar yapılandırılabilir:
- KeepAliveInterval - Proxy'lerin bağlantıyı açık tutmasını sağlamak için istemciye "ping" çerçeveleri gönderme sıklığı. Varsayılan değer iki dakikadır.
- AllowedOrigins - WebSocket istekleri için izin verilen Kaynak üst bilgi değerlerinin listesi. Varsayılan olarak tüm çıkış noktalarına izin verilir. Ayrıntılar için aşağıdaki "WebSocket kaynak kısıtlaması" bölümüne bakın.
var webSocketOptions = new WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(120),
};
app.UseWebSockets(webSocketOptions);
WebSocket isteklerini kabul etme
İstek yaşam döngüsünün sonraki bölümlerinde (örneğin, yönteminde Configure
veya eylem yönteminde) bunun bir WebSocket isteği olup olmadığını denetleyin ve WebSocket isteğini kabul edin.
Aşağıdaki örnek, yönteminin sonraki bölümlerinde verilmiştir Configure
:
app.Use(async (context, next) =>
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
using (WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync())
{
await Echo(context, webSocket);
}
}
else
{
context.Response.StatusCode = (int) HttpStatusCode.BadRequest;
}
}
else
{
await next();
}
});
WebSocket isteği herhangi bir URL'de gelebilir, ancak bu örnek kod yalnızca için /ws
istekleri kabul eder.
Benzer bir yaklaşım bir denetleyici yönteminde de ele alınabilir:
public class WebSocketController : ControllerBase
{
[HttpGet("/ws")]
public async Task Get()
{
if (HttpContext.WebSockets.IsWebSocketRequest)
{
using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
await Echo(webSocket);
}
else
{
HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}
WebSocket kullanırken, bağlantı süresi boyunca ara yazılım işlem hattını çalışır durumda tutmanız gerekir . Ara yazılım işlem hattı sona erdikten sonra WebSocket iletisi göndermeye veya almaya çalışırsanız, aşağıdaki gibi bir özel durumla karşılaşabilirsiniz:
System.Net.WebSockets.WebSocketException (0x80004005): The remote party closed the WebSocket connection without completing the close handshake. ---> System.ObjectDisposedException: Cannot write to the response body, the response has completed.
Object name: 'HttpResponseStream'.
WebSocket'e veri yazmak için arka plan hizmeti kullanıyorsanız ara yazılım işlem hattını çalışır durumda tuttuğunuzdan emin olun. Bunu bir TaskCompletionSource<TResult>kullanarak yapın. TaskCompletionSource
öğesini arka plan hizmetinize geçirin ve WebSocket ile bitirdiğinizde aramasını TrySetResult sağlayın. Task Ardındanawait
, aşağıdaki örnekte gösterildiği gibi istek sırasında özelliği:
app.Use(async (context, next) =>
{
using (WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync())
{
var socketFinishedTcs = new TaskCompletionSource<object>();
BackgroundSocketProcessor.AddSocket(webSocket, socketFinishedTcs);
await socketFinishedTcs.Task;
}
});
WebSocket kapalı özel durumu, bir eylem yönteminden çok erken geri dönerken de oluşabilir. Eylem yönteminde yuva kabul ederken, eylem yönteminden dönmeden önce yuvayı kullanan kodun tamamlanmasını bekleyin.
Önemli iş parçacığı sorunlarına neden olabileceğinden, yuvanın tamamlanmasını beklemek için hiçbir zaman , Task.Result
veya benzer engelleme çağrıları kullanmayınTask.Wait
. Her zaman kullanın await
.
İleti alma ve gönderme
yöntemi TCP AcceptWebSocketAsync
bağlantısını bir WebSocket bağlantısına yükselterek bir WebSocket nesne sağlar. WebSocket
İleti göndermek ve almak için nesnesini kullanın.
WebSocket isteğini kabul eden daha önce gösterilen kod, nesnesini bir Echo
yönteme geçirirWebSocket
. Kod bir ileti alır ve hemen aynı iletiyi geri gönderir. İstemci bağlantıyı kapatana kadar iletiler bir döngü içinde gönderilir ve alınır:
private async Task Echo(HttpContext context, WebSocket webSocket)
{
var buffer = new byte[1024 * 4];
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}
Döngüye başlamadan önce WebSocket bağlantısını kabul ederken ara yazılım işlem hattı sona erer. Yuva kapatılmaya devam ettikten sonra işlem hattı gevşer. Başka bir ifadeyle, WebSocket kabul edildiğinde istek işlem hattında ilerlemeyi durdurur. Döngü tamamlandığında ve yuva kapatıldığında istek işlem hattını yedekler.
İstemci bağlantısının kesilmesini işleme
Bağlantı kaybı nedeniyle istemcinin bağlantısı kesildiğinde sunucu otomatik olarak bilgilendirilir. Sunucu yalnızca istemci gönderirse bir bağlantı kesme iletisi alır ve bu işlem İnternet bağlantısı kesilirse yapılamaz. Böyle bir durumda işlem yapmak istiyorsanız, istemciden belirli bir zaman penceresi içinde hiçbir şey alınmadığında bir zaman aşımı ayarlayın.
İstemci her zaman ileti göndermiyorsa ve bağlantı boşta olduğu için zaman aşımına uğradıysanız, istemcinin her X saniyede bir ping iletisi göndermek için zamanlayıcı kullanmasını sağlayın. Sunucuda, bir ileti öncekinden sonraki 2*X saniye içinde gelmediyse bağlantıyı sonlandırın ve istemcinin bağlantısının kesildiğini bildirin. Ping iletisini tutabilecek ağ gecikmelerinde fazladan süre bırakmak için beklenen zaman aralığının iki katı kadar bekleyin.
Not
ManagedWebSocket
İç, seçenek sıfırdan büyükse KeepAliveInterval
(varsayılan olarak 30 saniyeye (TimeSpan.FromSeconds(30)
) kadar olan bağlantıyı canlı tutmak için Ping/Pong çerçevelerini örtük olarak işler.
WebSocket kaynak kısıtlaması
CORS tarafından sağlanan korumalar WebSockets için geçerli değildir. Tarayıcılar aşağıdakileri yapmaz:
- CORS uçuş öncesi istekleri gerçekleştirin.
- WebSocket istekleri yaparken üst bilgilerde
Access-Control
belirtilen kısıtlamalara uyun.
Ancak tarayıcılar WebSocket istekleri gönderirken üst bilgiyi gönderir Origin
. Uygulamalar, yalnızca beklenen kaynaklardan gelen WebSockets'e izin verildiğinden emin olmak için bu üst bilgileri doğrulayacak şekilde yapılandırılmalıdır.
Sunucunuzu "https://server.com" ve istemcinizi "https://client.com", "https://client.com" webSockets'in AllowedOrigins doğrulanması için listeye gidin.
var webSocketOptions = new WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(120),
};
webSocketOptions.AllowedOrigins.Add("https://client.com");
webSocketOptions.AllowedOrigins.Add("https://www.client.com");
app.UseWebSockets(webSocketOptions);
Not
Üst Origin
bilgi istemci tarafından denetlenebilir ve üst bilgi gibi Referer
sahte olabilir. Bu üst bilgileri kimlik doğrulama mekanizması olarak kullanmayın.
IIS/IIS Express desteği
Windows Server 2012 veya üzeri ve IIS/IIS Express 8 veya üzeri yüklü Windows 8 veya üzeri, WebSocket protokolü desteğine sahiptir.
Not
WebSockets, IIS Express kullanılırken her zaman etkinleştirilir.
IIS'de WebSockets'i etkinleştirme
Windows Server 2012 veya sonraki sürümlerde WebSocket protokolü desteğini etkinleştirmek için:
Not
IIS Express kullanılırken bu adımlar gerekli değildir
- Yönet menüsünden Rol ve Özellik Ekle sihirbazını veya Sunucu Yöneticisi'ndeki bağlantıyı kullanın.
- Rol Tabanlı veya Özellik Tabanlı Yükleme'yi seçin. İleri'yi seçin.
- Uygun sunucuyu seçin (yerel sunucu varsayılan olarak seçilidir). İleri'yi seçin.
- Roller ağacında Web Sunucusu'nu (IIS) genişletin, Web Sunucusu'nu genişletin ve ardından Uygulama Geliştirme'yi genişletin.
- WebSocket Protokolü'ne tıklayın. İleri'yi seçin.
- Ek özellikler gerekmiyorsa İleri'yi seçin.
- Yükle'yi seçin.
- Yükleme tamamlandığında, sihirbazdan çıkmak için Kapat'ı seçin.
Windows 8 veya sonraki sürümlerde WebSocket protokolü desteğini etkinleştirmek için:
Not
IIS Express kullanılırken bu adımlar gerekli değildir
- Denetim Masası>Programlar>Programlar ve Özellikler> gidinWindows özelliklerini aç veya kapat seçeneğine gidin (ekranın sol tarafında).
- Şu düğümleri açın: Internet Information Services>World Wide Web Services>Uygulama Geliştirme Özellikleri.
- WebSocket Protokolü özelliğini seçin. Tamam'ı seçin.
Node'da socket.io kullanırken WebSocket'i devre dışı bırakın.js
Node. üzerindeki socket.io WebSocket desteğini kullanıyorsanız, web.configjs veya applicationHost.config içindeki öğesini kullanarak webSocket
varsayılan IIS WebSocket modülünü devre dışı bırakın. Bu adım gerçekleştirilmezse, IIS WebSocket modülü Node yerine WebSocket iletişimini işlemeye çalışır.js ve uygulamayı seçin.
<system.webServer>
<webSocket enabled="false" />
</system.webServer>
Örnek uygulama
Bu makaleye eşlik eden örnek uygulama bir yankı uygulamasıdır. WebSocket bağlantılarını yapan bir web sayfası vardır ve sunucu aldığı tüm iletileri istemciye yeniden gönderir. Örnek uygulama, IIS Express ile Visual Studio'dan çalıştırılacak şekilde yapılandırılmadığından, ile bir komut kabuğunda dotnet run
uygulamayı çalıştırın ve tarayıcıda öğesine http://localhost:5000
gidin. Web sayfası bağlantı durumunu gösterir:
Gösterilen URL'ye WebSocket isteği göndermek için Bağlan'ı seçin. Bir test iletisi girin ve Gönder'i seçin. İşiniz bittiğinde Yuvayı Kapat'ı seçin. İletişim Günlüğü bölümü, her bir açma, gönderme ve kapatma eylemini olduğu gibi bildirir.
ASP.NET Core