Megosztás a következőn keresztül:


A WebSockets támogatása a ASP.NET Core-ban

Note

Ez nem a cikk legújabb verziója. Az aktuális kiadásról a cikk .NET 10-es verziójában olvashat.

Warning

A ASP.NET Core ezen verziója már nem támogatott. További információt a .NET és a .NET Core támogatási szabályzatában talál. A jelen cikk .NET 9-es verzióját lásd az aktuális kiadásért .

Ez a cikk bemutatja, hogyan kezdheti el a WebSockets használatát ASP.NET Core-ban. A WebSocket (RFC 6455) egy protokoll, amely lehetővé teszi a kétirányú állandó kommunikációs csatornákat TCP-kapcsolatokon keresztül. Olyan alkalmazásokban használják, amelyek kihasználják a gyors, valós idejű kommunikációt, például a csevegést, az irányítópultot és a játékalkalmazásokat.

Mintakód megtekintése vagy letöltése (letöltés, futtatás).

A Http/2 WebSockets támogatása

A WebSockets http/2-en keresztüli használata kihasználja az új funkciókat, például:

  • Fejléctömörítés.
  • Multiplexálás, amely csökkenti a kiszolgálóra irányuló több kéréshez szükséges időt és erőforrásokat.

Ezek a támogatott funkciók minden HTTP/2-kompatibilis platformon elérhetők Kestrel . A verzióegyeztetés automatikus a böngészőkben Kestrel, ezért nincs szükség új API-kra.

A .NET 7 bevezette a WebSocket-ek HTTP/2 támogatását a Kestrel esetében, a SignalR JavaScript-ügyfélhez, és a SignalR a Blazor WebAssembly-vel.

Note

A HTTP/2 WebSockets a GET helyett CONNECT-kéréseket használ, így előfordulhat, hogy a saját útvonalai és vezérlői frissítésre szorulnak. További információ: Http/2 WebSocket-támogatás hozzáadása meglévő vezérlőkhöz ebben a cikkben.

A Chrome, az Edge és a Firefox (128-es és újabb verziók) alapértelmezés szerint engedélyezve vannak a HTTP/2 WebSocket-ekkel. A beállítás ellenőrzéséhez vagy módosításához a Firefoxban nyissa meg a about:config menüt, és keresse meg a network.http.http2.websockets beállítást.

A WebSocketeket eredetileg HTTP/1.1-hez tervezték, de azóta a HTTP/2-n keresztüli működéshez lettek igazítva. (RFC 8441)

SignalR

ASP.NET Core SignalR egy olyan kódtár, amely leegyszerűsíti a valós idejű webes funkciók alkalmazásokhoz való hozzáadását. Lehetőség szerint WebSocketeket használ.

A legtöbb alkalmazás esetében a SignalR használatát javasoljuk a nyers WebSocket-ek helyett. SignalR:

  • Átviteli tartalékot biztosít azokhoz a környezetekhez, ahol a WebSockets nem érhető el.
  • Egy egyszerű távoli eljáráshívási alkalmazásmodellt biztosít.
  • A legtöbb forgatókönyvben nincs jelentős teljesítménybeli hátrány a nyers WebSocketekhez képest.

A HTTP/2-n keresztüli WebSocket-eket a következők támogatják:

  • ASP.NET Core SignalR JavaScript-ügyfél
  • ASP.NET Core SignalRBlazor WebAssembly

Egyes alkalmazások esetében a .NET-en található gRPC a WebSockets alternatívát kínál.

Prerequisites

  • Bármely operációs rendszer, amely támogatja a ASP.NET Core-t:
    • Windows 7 / Windows Server 2008 vagy újabb
    • Linux
    • macOS
  • Ha az alkalmazás Windows rendszeren fut IIS-vel:
  • Ha az alkalmazás HTTP.sysfut:
    • Windows 8 / Windows Server 2012 vagy újabb
  • A támogatott böngészőkről lásd: Használhatom.

A köztes szoftver konfigurálása

Adja hozzá a WebSockets köztes szoftverét a következő helyen Program.cs:

app.UseWebSockets();

A következő beállítások konfigurálhatók:

  • KeepAliveInterval – Milyen gyakran küldhet "ping" kereteket az ügyfélnek annak érdekében, hogy a proxyk nyitva tartsák a kapcsolatot. Az alapértelmezett érték két perc.
  • AllowedOrigins – A WebSocket-kérelmek engedélyezett forrásfejléc-értékeinek listája. Alapértelmezés szerint minden forrás engedélyezett. További információ: A WebSocket forráskorlátozása ebben a cikkben.
var webSocketOptions = new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromMinutes(2)
};

app.UseWebSockets(webSocketOptions);

WebSocket-kérelmek elfogadása

A kérelem életciklusának egy későbbi szakaszában (például egy műveletmetódusban Program.cs ) ellenőrizze, hogy webSocket-kérelemről van-e szó, és fogadja-e el a WebSocket-kérelmet.

A következő példa a következő későbbi szakaszból származik 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);
    }

});

Egy WebSocket-kérés bármilyen URL-címen bejöhet, de ez a mintakód csak a kéréseket /wsfogadja el.

Hasonló megközelítés egy vezérlőmetódusban is alkalmazható:

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 használata esetén a köztes szoftverfolyamatot a kapcsolat időtartamára kell futtatnia. Ha a köztesszoftver-folyamat befejeződése után megkísérli elküldeni vagy fogadni a WebSocket-üzenetet, az alábbihoz hasonló kivételt kaphat:

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'.

Ha háttérszolgáltatást használ adatok WebSocketbe való írásához, győződjön meg arról, hogy a köztesszoftver-folyamat fut. Ezt úgy teheted meg, hogy használsz egy TaskCompletionSource<TResult>. Adja át a TaskCompletionSource háttérszolgáltatásnak, és hívja meg TrySetResult-et, amikor befejezi a WebSocket használatát. Ezután állítsa be a await tulajdonságot a Task kérés során, ahogy az alábbi példában látható.

app.Run(async (context) =>
{
    using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
    var socketFinishedTcs = new TaskCompletionSource<object>();

    BackgroundSocketProcessor.AddSocket(webSocket, socketFinishedTcs);

    await socketFinishedTcs.Task;
});

A WebSocket zárt kivétele akkor is előfordulhat, ha túl hamar tér vissza egy műveletmetódusból. Ha egy szoftvercsatornát egy műveletmetódusban fogad el, várjon, amíg a szoftvercsatornát használó kód befejeződik, mielőtt visszatér a műveletmetódusból.

Soha ne használjon Task.Wait, Task.Result, vagy hasonló blokkoló hívásokat, hogy megvárja a socket teljes befejezését, mert ez súlyos szálkezelési problémákat okozhat. Mindig használja await.

HTTP/2 WebSocket-támogatás hozzáadása meglévő vezérlőkhöz

A .NET 7 bevezette a WebSocket-ek HTTP/2 támogatását a Kestrel esetében, a SignalR JavaScript-ügyfélhez, és a SignalR a Blazor WebAssembly-vel. A HTTP/2 WebSockets a GET helyett CONNECT-kéréseket használ. Ha korábban a vezérlőműveleti metódusában [HttpGet("/path")]-t használta a websocket-kérelmekhez, frissítse ezt [Route("/path")]-re.

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;
        }
    }

Compression

Warning

Ha titkosított kapcsolatokon keresztül engedélyezi a tömörítést, az alkalmazást támadásoknak teheti kiCRIME/BREACH. Ha bizalmas információkat küld, ne engedélyezze a tömörítést, és ne használja WebSocketMessageFlags.DisableCompression híváskor WebSocket.SendAsync. Ez a WebSocket mindkét oldalára vonatkozik. Vegye figyelembe, hogy a böngésző WebSockets API-ja nem rendelkezik konfigurációval a küldésenkénti tömörítés letiltására.

Ha az üzenetek websocketeken keresztüli tömörítésére van szükség, akkor az elfogadási kódnak meg kell adnia, hogy engedélyezi-e a tömörítést az alábbiak szerint:

using (var webSocket = await context.WebSockets.AcceptWebSocketAsync(
    new WebSocketAcceptContext { DangerousEnableCompression = true }))
{

}

WebSocketAcceptContext.ServerMaxWindowBits és WebSocketAcceptContext.DisableServerContextTakeover speciális beállítások, amelyek a tömörítés működését vezérlik.

A tömörítés egyeztetése az ügyfél és a kiszolgáló között a kapcsolat első létrehozásakor történik. A tárgyalásról a WebSocket RFC tömörítési bővítményeiben olvashat bővebben.

Note

Ha a tömörítési egyeztetést sem a kiszolgáló, sem az ügyfél nem fogadja el, a kapcsolat továbbra is létrejön. A kapcsolat azonban nem használ tömörítést üzenetek küldésekor és fogadásakor.

Üzenetek küldése és fogadása

A AcceptWebSocketAsync metódus frissíti a TCP-kapcsolatot egy WebSocket-kapcsolatra, és egy objektumot WebSocket biztosít. WebSocket Az objektum használatával üzeneteket küldhet és fogadhat.

A WebSocket-kérést elfogadó kód átadja az WebSocket objektumot egy Echo metódusnak. A kód egy üzenetet kap, és azonnal visszaküldi ugyanazt az üzenetet. Az üzeneteket a rendszer egy ciklusban küldi el és fogadja, amíg az ügyfél be nem zárja a kapcsolatot:

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);
}

Amikor elfogadja a WebSocket-kapcsolatot a hurok megkezdése előtt, a köztes szoftverfolyamat véget ér. A foglalat lezárásakor a csővezeték kiold. Ez azt jelzi, hogy a kérés a WebSocket elfogadásakor leáll a folyamat előrehaladtával. Ha a hurok befejeződött, és a csatlakozót bezárták, a kérés folytatja a folyamatot a csővezetéken felfelé.

Ügyfélleválasztások kezelése

A kiszolgáló nem kap automatikusan értesítést, amikor az ügyfél kapcsolat vesztése miatt kapcsolódik le. A kiszolgáló csak akkor kap leválasztási üzenetet, ha az ügyfél elküldi azt, ami nem végezhető el, ha az internetkapcsolat megszakad. Ha valamilyen műveletet szeretne elvégezni, ha ez történik, állítson be egy időtúllépést, miután az ügyfél nem kapott semmit egy adott időkereten belül.

Ha az ügyfél nem mindig küld üzeneteket, és nem szeretne időtúllépést elérni csak azért, mert a kapcsolat tétlenségbe kerül, az ügyfélnek célszerű időzítőt használni, hogy X másodpercenként küldjön egy pingüzenetet. A kiszolgálón, ha egy üzenet nem érkezett meg az előző után 2*X másodpercen belül, állítsa le a kapcsolatot, és jelentse, hogy az ügyfél megszakadt. Várjon a vártnál kétszer hosszabb ideig, hogy elegendő idő jusson a hálózati késésekre, amelyek késleltethetik a ping üzenetet.

A WebSocket forráskorlátozása

A CORS által biztosított védelem nem vonatkozik a WebSocketsre. A böngészők nem:

  • CORS-előrepülés előtti kérések végrehajtása.
  • A WebSocket-kérelmek létrehozásakor tartsa tiszteletben a fejlécekben Access-Control megadott korlátozásokat.

A böngészők azonban a WebSocket-kérelmek kiadásakor küldik el a Origin fejlécet. Az alkalmazásokat úgy kell konfigurálni, hogy érvényesítsék ezeket a fejléceket, hogy csak a várt forrásból származó WebSocketek legyenek engedélyezve.

Ha a kiszolgálót a "https://server.com"" és az ügyfelet a "https://client.com"" üzemelteted, akkor add hozzá a "https://client.com""-t a AllowedOrigins listához, hogy a WebSockets ellenőrizhesse.

var webSocketOptions = new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromMinutes(2)
};

webSocketOptions.AllowedOrigins.Add("https://client.com");
webSocketOptions.AllowedOrigins.Add("https://www.client.com");

app.UseWebSockets(webSocketOptions);

Note

A Origin fejlécet az ügyfél vezérli, és a Referer fejléc esetében, az hamisítható. Ne használja ezeket a fejléceket autentikációs mechanizmusként.

IIS/IIS Express-támogatás

A Windows Server 2012 vagy újabb, valamint a Windows 8 vagy újabb verzió támogatja a WebSocket protokollt, ha az IIS/IIS Express 8 vagy újabb van telepítve. A HTTP/2-n keresztüli WebSocket-eket azonban nem támogatja.

Note

A WebSockets mindig engedélyezve van az IIS Express használatakor.

WebSockets engedélyezése az IIS-en

A WebSocket protokoll támogatásának engedélyezése Windows Server 2012 vagy újabb rendszeren:

Note

Ezek a lépések nem szükségesek az IIS Express használatakor

  1. Használja a Szerepkörök és szolgáltatások hozzáadása varázslót a Kezelés menüből vagy a Kiszolgálókezelőhivatkozásából.
  2. Válassza a szerepköralapú vagy funkcióalapú telepítést. Válassza a Következőlehetőséget.
  3. Válassza ki a megfelelő kiszolgálót (alapértelmezés szerint a helyi kiszolgáló van kiválasztva). Válassza a Következőlehetőséget.
  4. Bontsa ki a webkiszolgálót (IIS) a Szerepkörök fában, bontsa ki a webkiszolgálót, majd bontsa ki az alkalmazásfejlesztést.
  5. Válassza a WebSocket Protocol lehetőséget. Válassza a Következőlehetőséget.
  6. Ha nincs szükség további funkciókra, válassza a Tovább gombot.
  7. Válassza a Telepítéslehetőséget.
  8. A telepítés befejezése után a Bezárás gombra kattintva lépjen ki a varázslóból.

A WebSocket protokoll támogatásának engedélyezése Windows 8 vagy újabb rendszeren:

Note

Ezek a lépések nem szükségesek az IIS Express használatakor

  1. Navigáljon a Vezérlőpult>Programok>Programok és szolgáltatások>Windows-funkciók be- és kikapcsolása menüpontra (a képernyő bal oldalán).
  2. Nyissa meg a következő csomópontokat: Internet Information Services>World Wide Web Services>Alkalmazásfejlesztési szolgáltatások.
  3. Válassza ki a WebSocket Protocol funkciót. Kattintson az OK gombra.

A WebSocket letiltása a socket.io Node.js használatakor

HaNode.jssocket.io WebSocket-támogatást használ, tiltsa le az alapértelmezett IIS WebSocket modult a webSocketweb.config vagy applicationHost.configelemével. Ha ez a lépés nem történik meg, az IIS WebSocket modul megpróbálja kezelni a WebSocket-kommunikációt Node.js és az alkalmazás helyett.

<system.webServer>
  <webSocket enabled="false" />
</system.webServer>

Mintaalkalmazás

A cikkhez mellékelt mintaalkalmazás egy echo-alkalmazás. Van egy weblapja, amely WebSocket-kapcsolatokat hoz létre, és a kiszolgáló újraküldi az ügyfélnek kapott üzeneteket. A mintaalkalmazás HTTP/2-n keresztül támogatja a WebSocketeket, ha a .NET 7 vagy újabb célzott keretrendszerét használja.

Futtassa az alkalmazást:

  • Alkalmazás futtatása a Visual Studióban: Nyissa meg a mintaprojektet a Visual Studióban, és nyomja le a Ctrl+F5 billentyűkombinációt a hibakereső nélküli futtatáshoz.
  • Az alkalmazás parancshéjban való futtatásához futtassa a parancsot dotnet run , és navigáljon egy böngészőben a következőre http://localhost:<port>: .

A weblap a kapcsolat állapotát jeleníti meg:

A weblap kezdeti állapota a WebSockets-kapcsolat előtt

Válassza a Csatlakozás lehetőséget , ha WebSocket-kérést szeretne küldeni a megjelenített URL-címre. Írjon be egy tesztüzenetet, és válassza a Küldés lehetőséget. Ha elkészült, válassza a Szoftvercsatorna bezárása lehetőséget. A Kommunikációs napló szakasz minden megnyitási, küldési és bezárásai műveletet jelez.

A weblap végleges állapota a WebSockets-kapcsolat és a tesztüzenetek elküldése és fogadása után

Ez a cikk bemutatja, hogyan kezdheti el a WebSockets használatát ASP.NET Core-ban. A WebSocket (RFC 6455) egy protokoll, amely lehetővé teszi a kétirányú állandó kommunikációs csatornákat TCP-kapcsolatokon keresztül. Olyan alkalmazásokban használják, amelyek kihasználják a gyors, valós idejű kommunikációt, például a csevegést, az irányítópultot és a játékalkalmazásokat.

Mintakód megtekintése vagy letöltése (letöltés, futtatás).

A Http/2 WebSockets támogatása

A WebSockets http/2-en keresztüli használata kihasználja az új funkciókat, például:

  • Fejléctömörítés.
  • Multiplexálás, amely csökkenti a kiszolgálóra irányuló több kéréshez szükséges időt és erőforrásokat.

Ezek a támogatott funkciók minden HTTP/2-kompatibilis platformon elérhetők Kestrel . A verzióegyeztetés automatikus a böngészőkben Kestrel, ezért nincs szükség új API-kra.

A .NET 7 bevezette a WebSocket-ek HTTP/2 támogatását a Kestrel esetében, a SignalR JavaScript-ügyfélhez, és a SignalR a Blazor WebAssembly-vel.

Note

A HTTP/2 WebSockets a GET helyett CONNECT-kéréseket használ, így előfordulhat, hogy a saját útvonalai és vezérlői frissítésre szorulnak. További információ: Http/2 WebSocket-támogatás hozzáadása meglévő vezérlőkhöz ebben a cikkben.

A Chrome, az Edge és a Firefox (128-es és újabb verziók) alapértelmezés szerint engedélyezve vannak a HTTP/2 WebSocket-ekkel. A beállítás ellenőrzéséhez vagy módosításához a Firefoxban nyissa meg a about:config menüt, és keresse meg a network.http.http2.websockets beállítást.

A WebSocketeket eredetileg HTTP/1.1-hez tervezték, de azóta a HTTP/2-n keresztüli működéshez lettek igazítva. (RFC 8441)

SignalR

ASP.NET Core SignalR egy olyan kódtár, amely leegyszerűsíti a valós idejű webes funkciók alkalmazásokhoz való hozzáadását. Lehetőség szerint WebSocketeket használ.

A legtöbb alkalmazás esetében a SignalR használatát javasoljuk a nyers WebSocket-ek helyett. SignalR:

  • Átviteli tartalékot biztosít azokhoz a környezetekhez, ahol a WebSockets nem érhető el.
  • Egy egyszerű távoli eljáráshívási alkalmazásmodellt biztosít.
  • A legtöbb forgatókönyvben nincs jelentős teljesítménybeli hátrány a nyers WebSocketekhez képest.

A HTTP/2-n keresztüli WebSocket-eket a következők támogatják:

  • ASP.NET Core SignalR JavaScript-ügyfél
  • ASP.NET Core SignalRBlazor WebAssembly

Egyes alkalmazások esetében a .NET-en található gRPC a WebSockets alternatívát kínál.

Prerequisites

  • Bármely operációs rendszer, amely támogatja a ASP.NET Core-t:
    • Windows 7 / Windows Server 2008 vagy újabb
    • Linux
    • macOS
  • Ha az alkalmazás Windows rendszeren fut IIS-vel:
  • Ha az alkalmazás HTTP.sysfut:
    • Windows 8 / Windows Server 2012 vagy újabb
  • A támogatott böngészőkről lásd: Használhatom.

A köztes szoftver konfigurálása

Adja hozzá a WebSockets köztes szoftverét a következő helyen Program.cs:

app.UseWebSockets();

A következő beállítások konfigurálhatók:

  • KeepAliveInterval – Milyen gyakran küldhet "ping" kereteket az ügyfélnek annak érdekében, hogy a proxyk nyitva tartsák a kapcsolatot. Az alapértelmezett érték két perc.
  • AllowedOrigins – A WebSocket-kérelmek engedélyezett forrásfejléc-értékeinek listája. Alapértelmezés szerint minden forrás engedélyezett. További információ: A WebSocket forráskorlátozása ebben a cikkben.
var webSocketOptions = new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromMinutes(2)
};

app.UseWebSockets(webSocketOptions);

WebSocket-kérelmek elfogadása

A kérelem életciklusának egy későbbi szakaszában (például egy műveletmetódusban Program.cs ) ellenőrizze, hogy webSocket-kérelemről van-e szó, és fogadja-e el a WebSocket-kérelmet.

A következő példa a következő későbbi szakaszból származik 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);
    }

});

Egy WebSocket-kérés bármilyen URL-címen bejöhet, de ez a mintakód csak a kéréseket /wsfogadja el.

Hasonló megközelítés egy vezérlőmetódusban is alkalmazható:

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 használata esetén a köztes szoftverfolyamatot a kapcsolat időtartamára kell futtatnia. Ha a köztesszoftver-folyamat befejeződése után megkísérli elküldeni vagy fogadni a WebSocket-üzenetet, az alábbihoz hasonló kivételt kaphat:

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'.

Ha háttérszolgáltatást használ adatok WebSocketbe való írásához, győződjön meg arról, hogy a köztesszoftver-folyamat fut. Ezt úgy teheted meg, hogy használsz egy TaskCompletionSource<TResult>. Adja át a TaskCompletionSource háttérszolgáltatásnak, és hívja meg TrySetResult-et, amikor befejezi a WebSocket használatát. Ezután állítsa be a await tulajdonságot a Task kérés során, ahogy az alábbi példában látható.

app.Run(async (context) =>
{
    using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
    var socketFinishedTcs = new TaskCompletionSource<object>();

    BackgroundSocketProcessor.AddSocket(webSocket, socketFinishedTcs);

    await socketFinishedTcs.Task;
});

A WebSocket zárt kivétele akkor is előfordulhat, ha túl hamar tér vissza egy műveletmetódusból. Ha egy szoftvercsatornát egy műveletmetódusban fogad el, várjon, amíg a szoftvercsatornát használó kód befejeződik, mielőtt visszatér a műveletmetódusból.

Soha ne használjon Task.Wait, Task.Result, vagy hasonló blokkoló hívásokat, hogy megvárja a socket teljes befejezését, mert ez súlyos szálkezelési problémákat okozhat. Mindig használja await.

HTTP/2 WebSocket-támogatás hozzáadása meglévő vezérlőkhöz

A .NET 7 bevezette a WebSocket-ek HTTP/2 támogatását a Kestrel esetében, a SignalR JavaScript-ügyfélhez, és a SignalR a Blazor WebAssembly-vel. A HTTP/2 WebSockets a GET helyett CONNECT-kéréseket használ. Ha korábban a vezérlőműveleti metódusában [HttpGet("/path")]-t használta a websocket-kérelmekhez, frissítse ezt [Route("/path")]-re.

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;
        }
    }

Compression

Warning

Ha titkosított kapcsolatokon keresztül engedélyezi a tömörítést, az alkalmazást támadásoknak teheti kiCRIME/BREACH. Ha bizalmas információkat küld, ne engedélyezze a tömörítést, és ne használja WebSocketMessageFlags.DisableCompression híváskor WebSocket.SendAsync. Ez a WebSocket mindkét oldalára vonatkozik. Vegye figyelembe, hogy a böngésző WebSockets API-ja nem rendelkezik konfigurációval a küldésenkénti tömörítés letiltására.

Ha az üzenetek websocketeken keresztüli tömörítésére van szükség, akkor az elfogadási kódnak meg kell adnia, hogy engedélyezi-e a tömörítést az alábbiak szerint:

using (var webSocket = await context.WebSockets.AcceptWebSocketAsync(
    new WebSocketAcceptContext { DangerousEnableCompression = true }))
{

}

WebSocketAcceptContext.ServerMaxWindowBits és WebSocketAcceptContext.DisableServerContextTakeover speciális beállítások, amelyek a tömörítés működését vezérlik.

A tömörítés egyeztetése az ügyfél és a kiszolgáló között a kapcsolat első létrehozásakor történik. A tárgyalásról a WebSocket RFC tömörítési bővítményeiben olvashat bővebben.

Note

Ha a tömörítési egyeztetést sem a kiszolgáló, sem az ügyfél nem fogadja el, a kapcsolat továbbra is létrejön. A kapcsolat azonban nem használ tömörítést üzenetek küldésekor és fogadásakor.

Üzenetek küldése és fogadása

A AcceptWebSocketAsync metódus frissíti a TCP-kapcsolatot egy WebSocket-kapcsolatra, és egy objektumot WebSocket biztosít. WebSocket Az objektum használatával üzeneteket küldhet és fogadhat.

A WebSocket-kérést elfogadó kód átadja az WebSocket objektumot egy Echo metódusnak. A kód egy üzenetet kap, és azonnal visszaküldi ugyanazt az üzenetet. Az üzeneteket a rendszer egy ciklusban küldi el és fogadja, amíg az ügyfél be nem zárja a kapcsolatot:

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);
}

Amikor elfogadja a WebSocket-kapcsolatot a hurok megkezdése előtt, a köztes szoftverfolyamat véget ér. A foglalat lezárásakor a csővezeték kiold. Ez azt jelzi, hogy a kérés a WebSocket elfogadásakor leáll a folyamat előrehaladtával. Ha a hurok befejeződött, és a csatlakozót bezárták, a kérés folytatja a folyamatot a csővezetéken felfelé.

Ügyfélleválasztások kezelése

A kiszolgáló nem kap automatikusan értesítést, amikor az ügyfél kapcsolat vesztése miatt kapcsolódik le. A kiszolgáló csak akkor kap leválasztási üzenetet, ha az ügyfél elküldi azt, ami nem végezhető el, ha az internetkapcsolat megszakad. Ha valamilyen műveletet szeretne elvégezni, ha ez történik, állítson be egy időtúllépést, miután az ügyfél nem kapott semmit egy adott időkereten belül.

Ha az ügyfél nem mindig küld üzeneteket, és nem szeretne időtúllépést elérni csak azért, mert a kapcsolat tétlenségbe kerül, az ügyfélnek célszerű időzítőt használni, hogy X másodpercenként küldjön egy pingüzenetet. A kiszolgálón, ha egy üzenet nem érkezett meg az előző után 2*X másodpercen belül, állítsa le a kapcsolatot, és jelentse, hogy az ügyfél megszakadt. Várjon a vártnál kétszer hosszabb ideig, hogy elegendő idő jusson a hálózati késésekre, amelyek késleltethetik a ping üzenetet.

A WebSocket forráskorlátozása

A CORS által biztosított védelem nem vonatkozik a WebSocketsre. A böngészők nem:

  • CORS-előrepülés előtti kérések végrehajtása.
  • A WebSocket-kérelmek létrehozásakor tartsa tiszteletben a fejlécekben Access-Control megadott korlátozásokat.

A böngészők azonban a WebSocket-kérelmek kiadásakor küldik el a Origin fejlécet. Az alkalmazásokat úgy kell konfigurálni, hogy érvényesítsék ezeket a fejléceket, hogy csak a várt forrásból származó WebSocketek legyenek engedélyezve.

Ha a kiszolgálót a "https://server.com"" és az ügyfelet a "https://client.com"" üzemelteted, akkor add hozzá a "https://client.com""-t a AllowedOrigins listához, hogy a WebSockets ellenőrizhesse.

var webSocketOptions = new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromMinutes(2)
};

webSocketOptions.AllowedOrigins.Add("https://client.com");
webSocketOptions.AllowedOrigins.Add("https://www.client.com");

app.UseWebSockets(webSocketOptions);

Note

A Origin fejlécet az ügyfél vezérli, és a Referer fejléc esetében, az hamisítható. Ne használja ezeket a fejléceket autentikációs mechanizmusként.

IIS/IIS Express-támogatás

A Windows Server 2012 vagy újabb, valamint a Windows 8 vagy újabb verzió támogatja a WebSocket protokollt, ha az IIS/IIS Express 8 vagy újabb van telepítve. A HTTP/2-n keresztüli WebSocket-eket azonban nem támogatja.

Note

A WebSockets mindig engedélyezve van az IIS Express használatakor.

WebSockets engedélyezése az IIS-en

A WebSocket protokoll támogatásának engedélyezése Windows Server 2012 vagy újabb rendszeren:

Note

Ezek a lépések nem szükségesek az IIS Express használatakor

  1. Használja a Szerepkörök és szolgáltatások hozzáadása varázslót a Kezelés menüből vagy a Kiszolgálókezelőhivatkozásából.
  2. Válassza a szerepköralapú vagy funkcióalapú telepítést. Válassza a Következőlehetőséget.
  3. Válassza ki a megfelelő kiszolgálót (alapértelmezés szerint a helyi kiszolgáló van kiválasztva). Válassza a Következőlehetőséget.
  4. Bontsa ki a webkiszolgálót (IIS) a Szerepkörök fában, bontsa ki a webkiszolgálót, majd bontsa ki az alkalmazásfejlesztést.
  5. Válassza a WebSocket Protocol lehetőséget. Válassza a Következőlehetőséget.
  6. Ha nincs szükség további funkciókra, válassza a Tovább gombot.
  7. Válassza a Telepítéslehetőséget.
  8. A telepítés befejezése után a Bezárás gombra kattintva lépjen ki a varázslóból.

A WebSocket protokoll támogatásának engedélyezése Windows 8 vagy újabb rendszeren:

Note

Ezek a lépések nem szükségesek az IIS Express használatakor

  1. Navigáljon a Vezérlőpult>Programok>Programok és szolgáltatások>Windows-funkciók be- és kikapcsolása menüpontra (a képernyő bal oldalán).
  2. Nyissa meg a következő csomópontokat: Internet Information Services>World Wide Web Services>Alkalmazásfejlesztési szolgáltatások.
  3. Válassza ki a WebSocket Protocol funkciót. Kattintson az OK gombra.

A WebSocket letiltása a socket.io Node.js használatakor

HaNode.jssocket.io WebSocket-támogatást használ, tiltsa le az alapértelmezett IIS WebSocket modult a webSocketweb.config vagy applicationHost.configelemével. Ha ez a lépés nem történik meg, az IIS WebSocket modul megpróbálja kezelni a WebSocket-kommunikációt Node.js és az alkalmazás helyett.

<system.webServer>
  <webSocket enabled="false" />
</system.webServer>

Mintaalkalmazás

A cikkhez mellékelt mintaalkalmazás egy echo-alkalmazás. Van egy weblapja, amely WebSocket-kapcsolatokat hoz létre, és a kiszolgáló újraküldi az ügyfélnek kapott üzeneteket. A mintaalkalmazás HTTP/2-n keresztül támogatja a WebSocketeket, ha a .NET 7 vagy újabb célzott keretrendszerét használja.

Futtassa az alkalmazást:

  • Alkalmazás futtatása a Visual Studióban: Nyissa meg a mintaprojektet a Visual Studióban, és nyomja le a Ctrl+F5 billentyűkombinációt a hibakereső nélküli futtatáshoz.
  • Az alkalmazás parancshéjban való futtatásához futtassa a parancsot dotnet run , és navigáljon egy böngészőben a következőre http://localhost:<port>: .

A weblap a kapcsolat állapotát jeleníti meg:

A weblap kezdeti állapota a WebSockets-kapcsolat előtt

Válassza a Csatlakozás lehetőséget , ha WebSocket-kérést szeretne küldeni a megjelenített URL-címre. Írjon be egy tesztüzenetet, és válassza a Küldés lehetőséget. Ha elkészült, válassza a Szoftvercsatorna bezárása lehetőséget. A Kommunikációs napló szakasz minden megnyitási, küldési és bezárásai műveletet jelez.

A weblap végleges állapota a WebSockets-kapcsolat és a tesztüzenetek elküldése és fogadása után

Ez a cikk bemutatja, hogyan kezdheti el a WebSockets használatát ASP.NET Core-ban. A WebSocket (RFC 6455) egy protokoll, amely lehetővé teszi a kétirányú állandó kommunikációs csatornákat TCP-kapcsolatokon keresztül. Olyan alkalmazásokban használják, amelyek kihasználják a gyors, valós idejű kommunikációt, például a csevegést, az irányítópultot és a játékalkalmazásokat.

Mintakód megtekintése vagy letöltése (letöltés, futtatás).

A Http/2 WebSockets támogatása

A WebSockets http/2-en keresztüli használata kihasználja az új funkciókat, például:

  • Fejléctömörítés.
  • Multiplexálás, amely csökkenti a kiszolgálóra irányuló több kéréshez szükséges időt és erőforrásokat.

Ezek a támogatott funkciók minden HTTP/2-kompatibilis platformon elérhetők Kestrel . A verzióegyeztetés automatikus a böngészőkben Kestrel, ezért nincs szükség új API-kra.

A .NET 7 bevezette a WebSocket-ek HTTP/2 támogatását a Kestrel esetében, a SignalR JavaScript-ügyfélhez, és a SignalR a Blazor WebAssembly-vel.

Note

A HTTP/2 WebSockets a GET helyett CONNECT-kéréseket használ, így előfordulhat, hogy a saját útvonalai és vezérlői frissítésre szorulnak. További információ: Http/2 WebSocket-támogatás hozzáadása meglévő vezérlőkhöz ebben a cikkben.

A Chrome, az Edge és a Firefox (128-es és újabb verziók) alapértelmezés szerint engedélyezve vannak a HTTP/2 WebSocket-ekkel. A beállítás ellenőrzéséhez vagy módosításához a Firefoxban nyissa meg a about:config menüt, és keresse meg a network.http.http2.websockets beállítást.

A WebSocketeket eredetileg HTTP/1.1-hez tervezték, de azóta a HTTP/2-n keresztüli működéshez lettek igazítva. (RFC 8441)

SignalR

ASP.NET Core SignalR egy olyan kódtár, amely leegyszerűsíti a valós idejű webes funkciók alkalmazásokhoz való hozzáadását. Lehetőség szerint WebSocketeket használ.

A legtöbb alkalmazás esetében a SignalR használatát javasoljuk a nyers WebSocket-ek helyett. SignalR:

  • Átviteli tartalékot biztosít azokhoz a környezetekhez, ahol a WebSockets nem érhető el.
  • Egy egyszerű távoli eljáráshívási alkalmazásmodellt biztosít.
  • A legtöbb forgatókönyvben nincs jelentős teljesítménybeli hátrány a nyers WebSocketekhez képest.

A HTTP/2-n keresztüli WebSocket-eket a következők támogatják:

  • ASP.NET Core SignalR JavaScript-ügyfél
  • ASP.NET Core SignalRBlazor WebAssembly

Egyes alkalmazások esetében a .NET-en található gRPC a WebSockets alternatívát kínál.

Prerequisites

  • Bármely operációs rendszer, amely támogatja a ASP.NET Core-t:
    • Windows 7 / Windows Server 2008 vagy újabb
    • Linux
    • macOS
  • Ha az alkalmazás Windows rendszeren fut IIS-vel:
  • Ha az alkalmazás HTTP.sysfut:
    • Windows 8 / Windows Server 2012 vagy újabb
  • A támogatott böngészőkről lásd: Használhatom.

A köztes szoftver konfigurálása

Adja hozzá a WebSockets köztes szoftverét a következő helyen Program.cs:

app.UseWebSockets();

A következő beállítások konfigurálhatók:

  • KeepAliveInterval – Milyen gyakran küldhet "ping" kereteket az ügyfélnek annak érdekében, hogy a proxyk nyitva tartsák a kapcsolatot. Az alapértelmezett érték két perc.
  • AllowedOrigins – A WebSocket-kérelmek engedélyezett forrásfejléc-értékeinek listája. Alapértelmezés szerint minden forrás engedélyezett. További információ: A WebSocket forráskorlátozása ebben a cikkben.
var webSocketOptions = new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromMinutes(2)
};

app.UseWebSockets(webSocketOptions);

WebSocket-kérelmek elfogadása

A kérelem életciklusának egy későbbi szakaszában (például egy műveletmetódusban Program.cs ) ellenőrizze, hogy webSocket-kérelemről van-e szó, és fogadja-e el a WebSocket-kérelmet.

A következő példa a következő későbbi szakaszból származik 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);
    }

});

Egy WebSocket-kérés bármilyen URL-címen bejöhet, de ez a mintakód csak a kéréseket /wsfogadja el.

Hasonló megközelítés egy vezérlőmetódusban is alkalmazható:

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 használata esetén a köztes szoftverfolyamatot a kapcsolat időtartamára kell futtatnia. Ha a köztesszoftver-folyamat befejeződése után megkísérli elküldeni vagy fogadni a WebSocket-üzenetet, az alábbihoz hasonló kivételt kaphat:

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'.

Ha háttérszolgáltatást használ adatok WebSocketbe való írásához, győződjön meg arról, hogy a köztesszoftver-folyamat fut. Ezt úgy teheted meg, hogy használsz egy TaskCompletionSource<TResult>. Adja át a TaskCompletionSource háttérszolgáltatásnak, és hívja meg TrySetResult-et, amikor befejezi a WebSocket használatát. Ezután állítsa be a await tulajdonságot a Task kérés során, ahogy az alábbi példában látható.

app.Run(async (context) =>
{
    using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
    var socketFinishedTcs = new TaskCompletionSource<object>();

    BackgroundSocketProcessor.AddSocket(webSocket, socketFinishedTcs);

    await socketFinishedTcs.Task;
});

A WebSocket zárt kivétele akkor is előfordulhat, ha túl hamar tér vissza egy műveletmetódusból. Ha egy szoftvercsatornát egy műveletmetódusban fogad el, várjon, amíg a szoftvercsatornát használó kód befejeződik, mielőtt visszatér a műveletmetódusból.

Soha ne használjon Task.Wait, Task.Result, vagy hasonló blokkoló hívásokat, hogy megvárja a socket teljes befejezését, mert ez súlyos szálkezelési problémákat okozhat. Mindig használja await.

HTTP/2 WebSocket-támogatás hozzáadása meglévő vezérlőkhöz

A .NET 7 bevezette a WebSocket-ek HTTP/2 támogatását a Kestrel esetében, a SignalR JavaScript-ügyfélhez, és a SignalR a Blazor WebAssembly-vel. A HTTP/2 WebSockets a GET helyett CONNECT-kéréseket használ. Ha korábban a vezérlőműveleti metódusában [HttpGet("/path")]-t használta a websocket-kérelmekhez, frissítse ezt [Route("/path")]-re.

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;
        }
    }

Compression

Warning

Ha titkosított kapcsolatokon keresztül engedélyezi a tömörítést, az alkalmazást támadásoknak teheti kiCRIME/BREACH. Ha bizalmas információkat küld, ne engedélyezze a tömörítést, és ne használja WebSocketMessageFlags.DisableCompression híváskor WebSocket.SendAsync. Ez a WebSocket mindkét oldalára vonatkozik. Vegye figyelembe, hogy a böngésző WebSockets API-ja nem rendelkezik konfigurációval a küldésenkénti tömörítés letiltására.

Ha az üzenetek websocketeken keresztüli tömörítésére van szükség, akkor az elfogadási kódnak meg kell adnia, hogy engedélyezi-e a tömörítést az alábbiak szerint:

using (var webSocket = await context.WebSockets.AcceptWebSocketAsync(
    new WebSocketAcceptContext { DangerousEnableCompression = true }))
{

}

WebSocketAcceptContext.ServerMaxWindowBits és WebSocketAcceptContext.DisableServerContextTakeover speciális beállítások, amelyek a tömörítés működését vezérlik.

A tömörítés egyeztetése az ügyfél és a kiszolgáló között a kapcsolat első létrehozásakor történik. A tárgyalásról a WebSocket RFC tömörítési bővítményeiben olvashat bővebben.

Note

Ha a tömörítési egyeztetést sem a kiszolgáló, sem az ügyfél nem fogadja el, a kapcsolat továbbra is létrejön. A kapcsolat azonban nem használ tömörítést üzenetek küldésekor és fogadásakor.

Üzenetek küldése és fogadása

A AcceptWebSocketAsync metódus frissíti a TCP-kapcsolatot egy WebSocket-kapcsolatra, és egy objektumot WebSocket biztosít. WebSocket Az objektum használatával üzeneteket küldhet és fogadhat.

A WebSocket-kérést elfogadó kód átadja az WebSocket objektumot egy Echo metódusnak. A kód egy üzenetet kap, és azonnal visszaküldi ugyanazt az üzenetet. Az üzeneteket a rendszer egy ciklusban küldi el és fogadja, amíg az ügyfél be nem zárja a kapcsolatot:

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);
}

Amikor elfogadja a WebSocket-kapcsolatot a hurok megkezdése előtt, a köztes szoftverfolyamat véget ér. A foglalat lezárásakor a csővezeték kiold. Ez azt jelzi, hogy a kérés a WebSocket elfogadásakor leáll a folyamat előrehaladtával. Ha a hurok befejeződött, és a csatlakozót bezárták, a kérés folytatja a folyamatot a csővezetéken felfelé.

Ügyfélleválasztások kezelése

A kiszolgáló nem kap automatikusan értesítést, amikor az ügyfél kapcsolat vesztése miatt kapcsolódik le. A kiszolgáló csak akkor kap leválasztási üzenetet, ha az ügyfél elküldi azt, ami nem végezhető el, ha az internetkapcsolat megszakad. Ha valamilyen műveletet szeretne elvégezni, ha ez történik, állítson be egy időtúllépést, miután az ügyfél nem kapott semmit egy adott időkereten belül.

Ha az ügyfél nem mindig küld üzeneteket, és nem szeretne időtúllépést elérni csak azért, mert a kapcsolat tétlenségbe kerül, az ügyfélnek célszerű időzítőt használni, hogy X másodpercenként küldjön egy pingüzenetet. A kiszolgálón, ha egy üzenet nem érkezett meg az előző után 2*X másodpercen belül, állítsa le a kapcsolatot, és jelentse, hogy az ügyfél megszakadt. Várjon a vártnál kétszer hosszabb ideig, hogy elegendő idő jusson a hálózati késésekre, amelyek késleltethetik a ping üzenetet.

A WebSocket forráskorlátozása

A CORS által biztosított védelem nem vonatkozik a WebSocketsre. A böngészők nem:

  • CORS-előrepülés előtti kérések végrehajtása.
  • A WebSocket-kérelmek létrehozásakor tartsa tiszteletben a fejlécekben Access-Control megadott korlátozásokat.

A böngészők azonban a WebSocket-kérelmek kiadásakor küldik el a Origin fejlécet. Az alkalmazásokat úgy kell konfigurálni, hogy érvényesítsék ezeket a fejléceket, hogy csak a várt forrásból származó WebSocketek legyenek engedélyezve.

Ha a kiszolgálót a "https://server.com"" és az ügyfelet a "https://client.com"" üzemelteted, akkor add hozzá a "https://client.com""-t a AllowedOrigins listához, hogy a WebSockets ellenőrizhesse.

var webSocketOptions = new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromMinutes(2)
};

webSocketOptions.AllowedOrigins.Add("https://client.com");
webSocketOptions.AllowedOrigins.Add("https://www.client.com");

app.UseWebSockets(webSocketOptions);

Note

A Origin fejlécet az ügyfél vezérli, és a Referer fejléc esetében, az hamisítható. Ne használja ezeket a fejléceket autentikációs mechanizmusként.

IIS/IIS Express-támogatás

A Windows Server 2012 vagy újabb, valamint a Windows 8 vagy újabb verzió támogatja a WebSocket protokollt, ha az IIS/IIS Express 8 vagy újabb van telepítve. A HTTP/2-n keresztüli WebSocket-eket azonban nem támogatja.

Note

A WebSockets mindig engedélyezve van az IIS Express használatakor.

WebSockets engedélyezése az IIS-en

A WebSocket protokoll támogatásának engedélyezése Windows Server 2012 vagy újabb rendszeren:

Note

Ezek a lépések nem szükségesek az IIS Express használatakor

  1. Használja a Szerepkörök és szolgáltatások hozzáadása varázslót a Kezelés menüből vagy a Kiszolgálókezelőhivatkozásából.
  2. Válassza a szerepköralapú vagy funkcióalapú telepítést. Válassza a Következőlehetőséget.
  3. Válassza ki a megfelelő kiszolgálót (alapértelmezés szerint a helyi kiszolgáló van kiválasztva). Válassza a Következőlehetőséget.
  4. Bontsa ki a webkiszolgálót (IIS) a Szerepkörök fában, bontsa ki a webkiszolgálót, majd bontsa ki az alkalmazásfejlesztést.
  5. Válassza a WebSocket Protocol lehetőséget. Válassza a Következőlehetőséget.
  6. Ha nincs szükség további funkciókra, válassza a Tovább gombot.
  7. Válassza a Telepítéslehetőséget.
  8. A telepítés befejezése után a Bezárás gombra kattintva lépjen ki a varázslóból.

A WebSocket protokoll támogatásának engedélyezése Windows 8 vagy újabb rendszeren:

Note

Ezek a lépések nem szükségesek az IIS Express használatakor

  1. Navigáljon a Vezérlőpult>Programok>Programok és szolgáltatások>Windows-funkciók be- és kikapcsolása menüpontra (a képernyő bal oldalán).
  2. Nyissa meg a következő csomópontokat: Internet Information Services>World Wide Web Services>Alkalmazásfejlesztési szolgáltatások.
  3. Válassza ki a WebSocket Protocol funkciót. Kattintson az OK gombra.

A WebSocket letiltása a socket.io Node.js használatakor

HaNode.jssocket.io WebSocket-támogatást használ, tiltsa le az alapértelmezett IIS WebSocket modult a webSocketweb.config vagy applicationHost.configelemével. Ha ez a lépés nem történik meg, az IIS WebSocket modul megpróbálja kezelni a WebSocket-kommunikációt Node.js és az alkalmazás helyett.

<system.webServer>
  <webSocket enabled="false" />
</system.webServer>

Mintaalkalmazás

A cikkhez mellékelt mintaalkalmazás egy echo-alkalmazás. Van egy weblapja, amely WebSocket-kapcsolatokat hoz létre, és a kiszolgáló újraküldi az ügyfélnek kapott üzeneteket. A mintaalkalmazás HTTP/2-n keresztül támogatja a WebSocketeket, ha a .NET 7 vagy újabb célzott keretrendszerét használja.

Futtassa az alkalmazást:

  • Alkalmazás futtatása a Visual Studióban: Nyissa meg a mintaprojektet a Visual Studióban, és nyomja le a Ctrl+F5 billentyűkombinációt a hibakereső nélküli futtatáshoz.
  • Az alkalmazás parancshéjban való futtatásához futtassa a parancsot dotnet run , és navigáljon egy böngészőben a következőre http://localhost:<port>: .

A weblap a kapcsolat állapotát jeleníti meg:

A weblap kezdeti állapota a WebSockets-kapcsolat előtt

Válassza a Csatlakozás lehetőséget , ha WebSocket-kérést szeretne küldeni a megjelenített URL-címre. Írjon be egy tesztüzenetet, és válassza a Küldés lehetőséget. Ha elkészült, válassza a Szoftvercsatorna bezárása lehetőséget. A Kommunikációs napló szakasz minden megnyitási, küldési és bezárásai műveletet jelez.

A weblap végleges állapota a WebSockets-kapcsolat és a tesztüzenetek elküldése és fogadása után

Ez a cikk bemutatja, hogyan kezdheti el a WebSockets használatát ASP.NET Core-ban. A WebSocket (RFC 6455) egy protokoll, amely lehetővé teszi a kétirányú állandó kommunikációs csatornákat TCP-kapcsolatokon keresztül. Olyan alkalmazásokban használják, amelyek kihasználják a gyors, valós idejű kommunikációt, például a csevegést, az irányítópultot és a játékalkalmazásokat.

Mintakód megtekintése vagy letöltése (letöltés, futtatás).

SignalR

ASP.NET Core SignalR egy olyan kódtár, amely leegyszerűsíti a valós idejű webes funkciók alkalmazásokhoz való hozzáadását. Lehetőség szerint WebSocketeket használ.

A legtöbb alkalmazás esetében a SignalR használatát javasoljuk a nyers websockets helyett. SignalR átviteli tartalékot biztosít azokhoz a környezetekhez, ahol a WebSockets nem érhető el. Emellett egy egyszerű távoli eljáráshívási alkalmazásmodellt is biztosít. A legtöbb forgatókönyvben SignalR nincs jelentős teljesítménybeli hátrány a nyers WebSocket-ekhez képest.

Egyes alkalmazások esetében a .NET-en található gRPC a WebSockets alternatívát kínál.

Prerequisites

  • Bármely operációs rendszer, amely támogatja a ASP.NET Core-t:
    • Windows 7 / Windows Server 2008 vagy újabb
    • Linux
    • macOS
  • Ha az alkalmazás Windows rendszeren fut IIS-vel:
  • Ha az alkalmazás HTTP.sysfut:
    • Windows 8 / Windows Server 2012 vagy újabb
  • A támogatott böngészőkről lásd: Használhatom.

A köztes szoftver konfigurálása

Adja hozzá a WebSockets köztes szoftverét a következő helyen Program.cs:

app.UseWebSockets();

A következő beállítások konfigurálhatók:

  • KeepAliveInterval – Milyen gyakran küldhet "ping" kereteket az ügyfélnek annak érdekében, hogy a proxyk nyitva tartsák a kapcsolatot. Az alapértelmezett érték két perc.
  • AllowedOrigins – A WebSocket-kérelmek engedélyezett forrásfejléc-értékeinek listája. Alapértelmezés szerint minden forrás engedélyezett. További információ: A WebSocket forráskorlátozása ebben a cikkben.
var webSocketOptions = new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromMinutes(2)
};

app.UseWebSockets(webSocketOptions);

WebSocket-kérelmek elfogadása

A kérelem életciklusának egy későbbi szakaszában (például egy műveletmetódusban Program.cs ) ellenőrizze, hogy webSocket-kérelemről van-e szó, és fogadja-e el a WebSocket-kérelmet.

A következő példa a következő későbbi szakaszból származik 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);
    }

});

Egy WebSocket-kérés bármilyen URL-címen bejöhet, de ez a mintakód csak a kéréseket /wsfogadja el.

Hasonló megközelítés egy vezérlőmetódusban is alkalmazható:

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 használata esetén a köztes szoftverfolyamatot a kapcsolat időtartamára kell futtatnia. Ha a köztesszoftver-folyamat befejeződése után megkísérli elküldeni vagy fogadni a WebSocket-üzenetet, az alábbihoz hasonló kivételt kaphat:

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'.

Ha háttérszolgáltatást használ adatok WebSocketbe való írásához, győződjön meg arról, hogy a köztesszoftver-folyamat fut. Ezt úgy teheted meg, hogy használsz egy TaskCompletionSource<TResult>. Adja át a TaskCompletionSource háttérszolgáltatásnak, és hívja meg TrySetResult-et, amikor befejezi a WebSocket használatát. Ezután állítsa be a await tulajdonságot a Task kérés során, ahogy az alábbi példában látható.

app.Run(async (context) =>
{
    using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
    var socketFinishedTcs = new TaskCompletionSource<object>();

    BackgroundSocketProcessor.AddSocket(webSocket, socketFinishedTcs);

    await socketFinishedTcs.Task;
});

A WebSocket zárt kivétele akkor is előfordulhat, ha túl hamar tér vissza egy műveletmetódusból. Ha egy szoftvercsatornát egy műveletmetódusban fogad el, várjon, amíg a szoftvercsatornát használó kód befejeződik, mielőtt visszatér a műveletmetódusból.

Soha ne használjon Task.Wait, Task.Result, vagy hasonló blokkoló hívásokat, hogy megvárja a socket teljes befejezését, mert ez súlyos szálkezelési problémákat okozhat. Mindig használja await.

Compression

Warning

Ha titkosított kapcsolatokon keresztül engedélyezi a tömörítést, az alkalmazást támadásoknak teheti kiCRIME/BREACH. Ha bizalmas információkat küld, ne engedélyezze a tömörítést, és ne használja WebSocketMessageFlags.DisableCompression híváskor WebSocket.SendAsync. Ez a WebSocket mindkét oldalára vonatkozik. Vegye figyelembe, hogy a böngésző WebSockets API-ja nem rendelkezik konfigurációval a küldésenkénti tömörítés letiltására.

Ha az üzenetek websocketeken keresztüli tömörítésére van szükség, akkor az elfogadási kódnak meg kell adnia, hogy engedélyezi-e a tömörítést az alábbiak szerint:

using (var webSocket = await context.WebSockets.AcceptWebSocketAsync(
    new WebSocketAcceptContext { DangerousEnableCompression = true }))
{

}

WebSocketAcceptContext.ServerMaxWindowBits és WebSocketAcceptContext.DisableServerContextTakeover speciális beállítások, amelyek a tömörítés működését vezérlik.

A tömörítés egyeztetése az ügyfél és a kiszolgáló között a kapcsolat első létrehozásakor történik. A tárgyalásról a WebSocket RFC tömörítési bővítményeiben olvashat bővebben.

Note

Ha a tömörítési egyeztetést sem a kiszolgáló, sem az ügyfél nem fogadja el, a kapcsolat továbbra is létrejön. A kapcsolat azonban nem használ tömörítést üzenetek küldésekor és fogadásakor.

Üzenetek küldése és fogadása

A AcceptWebSocketAsync metódus frissíti a TCP-kapcsolatot egy WebSocket-kapcsolatra, és egy objektumot WebSocket biztosít. WebSocket Az objektum használatával üzeneteket küldhet és fogadhat.

A WebSocket-kérést elfogadó kód átadja az WebSocket objektumot egy Echo metódusnak. A kód egy üzenetet kap, és azonnal visszaküldi ugyanazt az üzenetet. Az üzeneteket a rendszer egy ciklusban küldi el és fogadja, amíg az ügyfél be nem zárja a kapcsolatot:

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);
}

Amikor elfogadja a WebSocket-kapcsolatot a hurok megkezdése előtt, a köztes szoftverfolyamat véget ér. A foglalat lezárásakor a csővezeték kiold. Ez azt jelzi, hogy a kérés a WebSocket elfogadásakor leáll a folyamat előrehaladtával. Ha a hurok befejeződött, és a csatlakozót bezárták, a kérés folytatja a folyamatot a csővezetéken felfelé.

Ügyfélleválasztások kezelése

A kiszolgáló nem kap automatikusan értesítést, amikor az ügyfél kapcsolat vesztése miatt kapcsolódik le. A kiszolgáló csak akkor kap leválasztási üzenetet, ha az ügyfél elküldi azt, ami nem végezhető el, ha az internetkapcsolat megszakad. Ha valamilyen műveletet szeretne elvégezni, ha ez történik, állítson be egy időtúllépést, miután az ügyfél nem kapott semmit egy adott időkereten belül.

Ha az ügyfél nem mindig küld üzeneteket, és nem szeretne időtúllépést elérni csak azért, mert a kapcsolat tétlenségbe kerül, az ügyfélnek célszerű időzítőt használni, hogy X másodpercenként küldjön egy pingüzenetet. A kiszolgálón, ha egy üzenet nem érkezett meg az előző után 2*X másodpercen belül, állítsa le a kapcsolatot, és jelentse, hogy az ügyfél megszakadt. Várjon a vártnál kétszer hosszabb ideig, hogy elegendő idő jusson a hálózati késésekre, amelyek késleltethetik a ping üzenetet.

A WebSocket forráskorlátozása

A CORS által biztosított védelem nem vonatkozik a WebSocketsre. A böngészők nem:

  • CORS-előrepülés előtti kérések végrehajtása.
  • A WebSocket-kérelmek létrehozásakor tartsa tiszteletben a fejlécekben Access-Control megadott korlátozásokat.

A böngészők azonban a WebSocket-kérelmek kiadásakor küldik el a Origin fejlécet. Az alkalmazásokat úgy kell konfigurálni, hogy érvényesítsék ezeket a fejléceket, hogy csak a várt forrásból származó WebSocketek legyenek engedélyezve.

Ha a kiszolgálót a "https://server.com"" és az ügyfelet a "https://client.com"" üzemelteted, akkor add hozzá a "https://client.com""-t a AllowedOrigins listához, hogy a WebSockets ellenőrizhesse.

var webSocketOptions = new WebSocketOptions
{
    KeepAliveInterval = TimeSpan.FromMinutes(2)
};

webSocketOptions.AllowedOrigins.Add("https://client.com");
webSocketOptions.AllowedOrigins.Add("https://www.client.com");

app.UseWebSockets(webSocketOptions);

Note

A Origin fejlécet az ügyfél vezérli, és a Referer fejléc esetében, az hamisítható. Ne használja ezeket a fejléceket autentikációs mechanizmusként.

IIS/IIS Express-támogatás

A Windows Server 2012 vagy újabb és a Windows 8 vagy újabb, IIS/IIS Express 8 vagy újabb verzióval támogatja a WebSocket protokollt.

Note

A WebSockets mindig engedélyezve van az IIS Express használatakor.

WebSockets engedélyezése az IIS-en

A WebSocket protokoll támogatásának engedélyezése Windows Server 2012 vagy újabb rendszeren:

Note

Ezek a lépések nem szükségesek az IIS Express használatakor

  1. Használja a Szerepkörök és szolgáltatások hozzáadása varázslót a Kezelés menüből vagy a Kiszolgálókezelőhivatkozásából.
  2. Válassza a szerepköralapú vagy funkcióalapú telepítést. Válassza a Következőlehetőséget.
  3. Válassza ki a megfelelő kiszolgálót (alapértelmezés szerint a helyi kiszolgáló van kiválasztva). Válassza a Következőlehetőséget.
  4. Bontsa ki a webkiszolgálót (IIS) a Szerepkörök fában, bontsa ki a webkiszolgálót, majd bontsa ki az alkalmazásfejlesztést.
  5. Válassza a WebSocket Protocol lehetőséget. Válassza a Következőlehetőséget.
  6. Ha nincs szükség további funkciókra, válassza a Tovább gombot.
  7. Válassza a Telepítéslehetőséget.
  8. A telepítés befejezése után a Bezárás gombra kattintva lépjen ki a varázslóból.

A WebSocket protokoll támogatásának engedélyezése Windows 8 vagy újabb rendszeren:

Note

Ezek a lépések nem szükségesek az IIS Express használatakor

  1. Navigáljon a Vezérlőpult>Programok>Programok és szolgáltatások>Windows-funkciók be- és kikapcsolása menüpontra (a képernyő bal oldalán).
  2. Nyissa meg a következő csomópontokat: Internet Information Services>World Wide Web Services>Alkalmazásfejlesztési szolgáltatások.
  3. Válassza ki a WebSocket Protocol funkciót. Kattintson az OK gombra.

A WebSocket letiltása a socket.io Node.js használatakor

HaNode.jssocket.io WebSocket-támogatást használ, tiltsa le az alapértelmezett IIS WebSocket modult a webSocketweb.config vagy applicationHost.configelemével. Ha ez a lépés nem történik meg, az IIS WebSocket modul megpróbálja kezelni a WebSocket-kommunikációt Node.js és az alkalmazás helyett.

<system.webServer>
  <webSocket enabled="false" />
</system.webServer>

Mintaalkalmazás

A cikkhez mellékelt mintaalkalmazás egy echo-alkalmazás. Van egy weblapja, amely WebSocket-kapcsolatokat hoz létre, és a kiszolgáló újraküldi az ügyfélnek kapott üzeneteket. A mintaalkalmazás nincs konfigurálva arra, hogy a Visual Studio-val az IIS Express használatával fusson, ezért futtassa az alkalmazást egy parancshéjban dotnet run, és navigáljon a böngészőben a következő helyre: http://localhost:<port>. A weblap a kapcsolat állapotát jeleníti meg:

A weblap kezdeti állapota a WebSockets-kapcsolat előtt

Válassza a Csatlakozás lehetőséget , ha WebSocket-kérést szeretne küldeni a megjelenített URL-címre. Írjon be egy tesztüzenetet, és válassza a Küldés lehetőséget. Ha elkészült, válassza a Szoftvercsatorna bezárása lehetőséget. A Kommunikációs napló szakasz minden megnyitási, küldési és bezárásai műveletet jelez.

A weblap végleges állapota a WebSockets-kapcsolat és a tesztüzenetek elküldése és fogadása után

Ez a cikk bemutatja, hogyan kezdheti el a WebSockets használatát ASP.NET Core-ban. A WebSocket (RFC 6455) egy protokoll, amely lehetővé teszi a kétirányú állandó kommunikációs csatornákat TCP-kapcsolatokon keresztül. Olyan alkalmazásokban használják, amelyek kihasználják a gyors, valós idejű kommunikációt, például a csevegést, az irányítópultot és a játékalkalmazásokat.

Mintakód megtekintése vagy letöltése (hogyan töltsük le). Hogyan fussunk.

SignalR

ASP.NET Core SignalR egy olyan kódtár, amely leegyszerűsíti a valós idejű webes funkciók alkalmazásokhoz való hozzáadását. Lehetőség szerint WebSocketeket használ.

A legtöbb alkalmazás esetében a SignalR használatát javasoljuk a nyers websockets helyett. SignalR átviteli tartalékot biztosít azokhoz a környezetekhez, ahol a WebSockets nem érhető el. Emellett egy egyszerű távoli eljáráshívási alkalmazásmodellt is biztosít. A legtöbb forgatókönyvben SignalR nincs jelentős teljesítménybeli hátrány a nyers WebSocket-ekhez képest.

Egyes alkalmazások esetében a .NET-en található gRPC a WebSockets alternatívát kínál.

Prerequisites

  • Bármely operációs rendszer, amely támogatja a ASP.NET Core-t:
    • Windows 7 / Windows Server 2008 vagy újabb
    • Linux
    • macOS
  • Ha az alkalmazás Windows rendszeren fut IIS-vel:
  • Ha az alkalmazás HTTP.sysfut:
    • Windows 8 / Windows Server 2012 vagy újabb
  • A támogatott böngészőkről lásd: Használhatom.

A köztes szoftver konfigurálása

Adja hozzá a WebSockets köztes szoftvereket az ConfigureStartup osztály metódusához:

app.UseWebSockets();

Note

A WebSocket-kérések vezérlőben való elfogadása esetén a app.UseWebSockets hívásnak meg kell történnie, mielőtt a app.UseEndpoints hívásra sor kerül.

A következő beállítások konfigurálhatók:

  • KeepAliveInterval – Milyen gyakran küldhet "ping" kereteket az ügyfélnek annak érdekében, hogy a proxyk nyitva tartsák a kapcsolatot. Az alapértelmezett érték két perc.
  • AllowedOrigins – A WebSocket-kérelmek engedélyezett forrásfejléc-értékeinek listája. Alapértelmezés szerint minden forrás engedélyezett. Részletekért lásd a "WebSocket forráskorlátozása" című témakört.
var webSocketOptions = new WebSocketOptions()
{
    KeepAliveInterval = TimeSpan.FromSeconds(120),
};

app.UseWebSockets(webSocketOptions);

WebSocket-kérelmek elfogadása

A kérelem életciklusának későbbi szakaszában (például a Configure metódusban vagy egy műveletmetódusban) ellenőrizze, hogy ez egy WebSocket-kérelem, és fogadja-e el a WebSocket-kérelmet.

A következő példa a metódus későbbi szakaszából származik 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();
    }

});

Egy WebSocket-kérés bármilyen URL-címen bejöhet, de ez a mintakód csak a kéréseket /wsfogadja el.

Hasonló megközelítés egy vezérlőmetódusban is alkalmazható:

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 használata esetén a köztes szoftverfolyamatot a kapcsolat időtartamára kell futtatnia. Ha a köztesszoftver-folyamat befejeződése után megkísérli elküldeni vagy fogadni a WebSocket-üzenetet, az alábbihoz hasonló kivételt kaphat:

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'.

Ha háttérszolgáltatást használ adatok WebSocketbe való írásához, győződjön meg arról, hogy a köztesszoftver-folyamat fut. Ezt úgy teheted meg, hogy használsz egy TaskCompletionSource<TResult>. Adja át a TaskCompletionSource háttérszolgáltatásnak, és hívja meg TrySetResult-et, amikor befejezi a WebSocket használatát. Ezután állítsa be a await tulajdonságot a Task kérés során, ahogy az alábbi példában látható.

app.Use(async (context, next) =>
{
    using (WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync())
    {
        var socketFinishedTcs = new TaskCompletionSource<object>();

        BackgroundSocketProcessor.AddSocket(webSocket, socketFinishedTcs);

        await socketFinishedTcs.Task;
    }
});

A WebSocket zárt kivétele akkor is előfordulhat, ha túl hamar tér vissza egy műveletmetódusból. Ha egy szoftvercsatornát egy műveletmetódusban fogad el, várjon, amíg a szoftvercsatornát használó kód befejeződik, mielőtt visszatér a műveletmetódusból.

Soha ne használjon Task.Wait, Task.Result, vagy hasonló blokkoló hívásokat, hogy megvárja a socket teljes befejezését, mert ez súlyos szálkezelési problémákat okozhat. Mindig használja await.

Üzenetek küldése és fogadása

A AcceptWebSocketAsync metódus frissíti a TCP-kapcsolatot egy WebSocket-kapcsolatra, és egy objektumot WebSocket biztosít. WebSocket Az objektum használatával üzeneteket küldhet és fogadhat.

A WebSocket-kérést elfogadó kód átadja az WebSocket objektumot egy Echo metódusnak. A kód egy üzenetet kap, és azonnal visszaküldi ugyanazt az üzenetet. Az üzeneteket a rendszer egy ciklusban küldi el és fogadja, amíg az ügyfél be nem zárja a kapcsolatot:

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);
}

Amikor elfogadja a WebSocket-kapcsolatot a hurok megkezdése előtt, a köztes szoftverfolyamat véget ér. A foglalat lezárásakor a csővezeték kiold. Ez azt jelzi, hogy a kérés a WebSocket elfogadásakor leáll a folyamat előrehaladtával. Ha a hurok befejeződött, és a csatlakozót bezárták, a kérés folytatja a folyamatot a csővezetéken felfelé.

Ügyfélleválasztások kezelése

A kiszolgáló nem kap automatikusan értesítést, amikor az ügyfél kapcsolat vesztése miatt kapcsolódik le. A kiszolgáló csak akkor kap leválasztási üzenetet, ha az ügyfél elküldi azt, ami nem végezhető el, ha az internetkapcsolat megszakad. Ha valamilyen műveletet szeretne elvégezni, ha ez történik, állítson be egy időtúllépést, miután az ügyfél nem kapott semmit egy adott időkereten belül.

Ha az ügyfél nem mindig küld üzeneteket, és nem szeretne időtúllépést elérni csak azért, mert a kapcsolat tétlenségbe kerül, az ügyfélnek célszerű időzítőt használni, hogy X másodpercenként küldjön egy pingüzenetet. A kiszolgálón, ha egy üzenet nem érkezett meg az előző után 2*X másodpercen belül, állítsa le a kapcsolatot, és jelentse, hogy az ügyfél megszakadt. Várjon a vártnál kétszer hosszabb ideig, hogy elegendő idő jusson a hálózati késésekre, amelyek késleltethetik a ping üzenetet.

Note

A belső ManagedWebSocket implicit módon kezeli a Ping/Pong kereteket, hogy a kapcsolat fennmaradjon, ha a KeepAliveInterval opció nagyobb, mint nulla, ez alapértelmezés szerint 30 másodperc (TimeSpan.FromSeconds(30)).

A WebSocket forráskorlátozása

A CORS által biztosított védelem nem vonatkozik a WebSocketsre. A böngészők nem:

  • CORS-előrepülés előtti kérések végrehajtása.
  • A WebSocket-kérelmek létrehozásakor tartsa tiszteletben a fejlécekben Access-Control megadott korlátozásokat.

A böngészők azonban a WebSocket-kérelmek kiadásakor küldik el a Origin fejlécet. Az alkalmazásokat úgy kell konfigurálni, hogy érvényesítsék ezeket a fejléceket, hogy csak a várt forrásból származó WebSocketek legyenek engedélyezve.

Ha a kiszolgálót a "https://server.com"" és az ügyfelet a "https://client.com"" üzemelteted, akkor add hozzá a "https://client.com""-t a AllowedOrigins listához, hogy a WebSockets ellenőrizhesse.

var webSocketOptions = new WebSocketOptions()
{
    KeepAliveInterval = TimeSpan.FromSeconds(120),
};
webSocketOptions.AllowedOrigins.Add("https://client.com");
webSocketOptions.AllowedOrigins.Add("https://www.client.com");

app.UseWebSockets(webSocketOptions);

Note

A Origin fejlécet az ügyfél vezérli, és a Referer fejléc esetében, az hamisítható. Ne használja ezeket a fejléceket autentikációs mechanizmusként.

IIS/IIS Express-támogatás

A Windows Server 2012 vagy újabb és a Windows 8 vagy újabb, IIS/IIS Express 8 vagy újabb verzióval támogatja a WebSocket protokollt.

Note

A WebSockets mindig engedélyezve van az IIS Express használatakor.

WebSockets engedélyezése az IIS-en

A WebSocket protokoll támogatásának engedélyezése Windows Server 2012 vagy újabb rendszeren:

Note

Ezek a lépések nem szükségesek az IIS Express használatakor

  1. Használja a Szerepkörök és szolgáltatások hozzáadása varázslót a Kezelés menüből vagy a Kiszolgálókezelőhivatkozásából.
  2. Válassza a szerepköralapú vagy funkcióalapú telepítést. Válassza a Következőlehetőséget.
  3. Válassza ki a megfelelő kiszolgálót (alapértelmezés szerint a helyi kiszolgáló van kiválasztva). Válassza a Következőlehetőséget.
  4. Bontsa ki a webkiszolgálót (IIS) a Szerepkörök fában, bontsa ki a webkiszolgálót, majd bontsa ki az alkalmazásfejlesztést.
  5. Válassza a WebSocket Protocol lehetőséget. Válassza a Következőlehetőséget.
  6. Ha nincs szükség további funkciókra, válassza a Tovább gombot.
  7. Válassza a Telepítéslehetőséget.
  8. A telepítés befejezése után a Bezárás gombra kattintva lépjen ki a varázslóból.

A WebSocket protokoll támogatásának engedélyezése Windows 8 vagy újabb rendszeren:

Note

Ezek a lépések nem szükségesek az IIS Express használatakor

  1. Navigáljon a Vezérlőpult>Programok>Programok és szolgáltatások>Windows-funkciók be- és kikapcsolása menüpontra (a képernyő bal oldalán).
  2. Nyissa meg a következő csomópontokat: Internet Information Services>World Wide Web Services>Alkalmazásfejlesztési szolgáltatások.
  3. Válassza ki a WebSocket Protocol funkciót. Kattintson az OK gombra.

A WebSocket letiltása a socket.io Node.js használatakor

HaNode.jssocket.io WebSocket-támogatást használ, tiltsa le az alapértelmezett IIS WebSocket modult a webSocketweb.config vagy applicationHost.configelemével. Ha ez a lépés nem történik meg, az IIS WebSocket modul megpróbálja kezelni a WebSocket-kommunikációt Node.js és az alkalmazás helyett.

<system.webServer>
  <webSocket enabled="false" />
</system.webServer>

Mintaalkalmazás

A cikkhez mellékelt mintaalkalmazás egy echo-alkalmazás. Van egy weblapja, amely WebSocket-kapcsolatokat hoz létre, és a kiszolgáló újraküldi az ügyfélnek kapott üzeneteket. A mintaalkalmazás nincs konfigurálva arra, hogy a Visual Studio-val az IIS Express használatával fusson, ezért futtassa az alkalmazást egy parancshéjban dotnet run, és navigáljon a böngészőben a következő helyre: http://localhost:5000. A weblap a kapcsolat állapotát jeleníti meg:

A weblap kezdeti állapota a WebSockets-kapcsolat előtt

Válassza a Csatlakozás lehetőséget , ha WebSocket-kérést szeretne küldeni a megjelenített URL-címre. Írjon be egy tesztüzenetet, és válassza a Küldés lehetőséget. Ha elkészült, válassza a Szoftvercsatorna bezárása lehetőséget. A Kommunikációs napló szakasz minden megnyitási, küldési és bezárásai műveletet jelez.

A weblap végleges állapota a WebSockets-kapcsolat és a tesztüzenetek elküldése és fogadása után