0

WEB SOCKET COMANDOS E FUNÇÔES

A
Alfredo Neto

WEB SOCKET Comandos e funções

WEB SOCKET Comandos e funções: aspi.net core:


Suporte ao WebSockets no ASP.NET Core

  • 01/11/2020
  • 4 minutos para o fim da leitura

Por Tom Dykstra e Andrew Stanton-Nurse

Este artigo explica como começar a usar o WebSockets no ASP.NET Core. WebSocket (RFC 6455) é um protocolo que permite canais de comunicação persistentes bidirecionais em conexões TCP. Ele é usado em aplicativos que se beneficiam de comunicação rápida e em tempo real, como chat, painel e aplicativos de jogos.

Exibir ou baixar o código de exemplo ( comobaixar). Como executaro .

SignalR

ASP.NET Core SignalR é uma biblioteca que simplifica a adição de funcionalidades da Web em tempo real aos aplicativos. Ele usa WebSockets sempre que possível.

Para a maioria dos aplicativos, é SignalR recomendável sobre WebSockets brutos. SignalR fornece fallback de transporte para ambientes em que o WebSockets não está disponível. Ele também fornece um modelo de aplicativo de chamada de procedimento remoto básico. E, na maioria dos cenários, SignalR não tem nenhuma desvantagem de desempenho significativa em comparação com o uso de WebSockets brutos.

Para alguns aplicativos, o gRPC no .NET fornece uma alternativa ao WebSockets.

Pré-requisitos

  • Qualquer sistema operacional compatível com o ASP.NET Core:
  • Windows 7/Windows Server 2008 ou posterior
  • Linux
  • macOS
  • Se o aplicativo é executado no Windows com o IIS:
  • Windows 8/Windows Server 2012 ou posterior
  • IIS 8/IIS 8 Express
  • O WebSockets deve estar habilitado. Consulte a seção suporte IIS Express IIS.
  • Se o aplicativo é executado no HTTP.sys:
  • Windows 8/Windows Server 2012 ou posterior
  • Para saber quais são os navegadores compatíveis, confira https://caniuse.com/#feat=websockets.

Configurar o middleware

Adicione o middleware do WebSockets no método Configure da classe Startup:

C#

Copiar

app.UseWebSockets();

 Observação


Se você quiser aceitar solicitações WebSocket em um controlador, a chamada para app.UseWebSockets deve ocorrer antes de app.UseEndpoints .

As seguintes configurações podem ser definidas:

  • KeepAliveInterval – a frequência para enviar quadros "ping" ao cliente para garantir que os proxies mantenham a conexão aberta. O padrão é dois minutos.
  • AllowedOrigins – Uma lista de valores de cabeçalho de origem permitidos para solicitações do WebSocket. Por padrão, todas as origens são permitidas. Consulte "Restrição de origem do WebSocket" abaixo para obter detalhes.

C#

Copiar

var webSocketOptions = new WebSocketOptions() 
{
    KeepAliveInterval = TimeSpan.FromSeconds(120),
};

app.UseWebSockets(webSocketOptions);

Aceitar solicitações do WebSocket

Futuramente no ciclo de vida da solicitação (mais tarde no método Configure ou em um método de ação, por exemplo), verifique se é uma solicitação do WebSocket e aceite-a.

O exemplo a seguir é de uma fase posterior do método Configure:

C#

Copiar

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

});

Uma solicitação do WebSocket pode entrar em qualquer URL, mas esse código de exemplo aceita apenas solicitações de /ws.

Uma abordagem semelhante pode ser usada em um método de controlador:

C#

Copiar

public class WebSocketController : ControllerBase
{
    [HttpGet("/ws")]
    public async Task Get()
    {
        if (HttpContext.WebSockets.IsWebSocketRequest)
        {
            using WebSocket webSocket = await 
                               HttpContext.WebSockets.AcceptWebSocketAsync();
            await Echo(HttpContext, webSocket);
        }
        else
        {
            HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
        }
    }

Ao usar um WebSocket, você deve manter o pipeline de middleware em execução durante a conexão. Se tentar enviar ou receber uma mensagem do WebSocket após o término do pipeline de middleware, você poderá receber uma exceção semelhante à seguinte:

Copiar

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

Se você estiver usando um serviço em segundo plano para gravar dados em um WebSocket, mantenha o pipeline do middleware em execução. Faça isso usando um TaskCompletionSource<TResult>. Passe o TaskCompletionSource ao seu serviço em segundo plano e faça-o chamar TrySetResult quando terminar com o WebSocket. Em seguida await a propriedade Task durante a solicitação, conforme é mostrado no exemplo a seguir:

C#

Copiar

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 exceção fechada do WebSocket também pode ocorrer ao retornar muito cedo de um método de ação. Ao aceitar um soquete em um método de ação, aguarde até que o código que usa o soquete seja concluído antes de retornar do método de ação.

Nunca use Task.WaitTask.Result ou chamadas de bloqueio semelhantes para aguardar a conclusão do soquete, pois isso pode causar sérios problemas de threading. Sempre use await.

Enviar e receber mensagens

O método AcceptWebSocketAsync atualiza a conexão TCP para uma conexão WebSocket e fornece um objeto WebSocket. Use o objeto WebSocket para enviar e receber mensagens.

O código mostrado anteriormente que aceita a solicitação do WebSocket passa o objeto WebSocket para um método Echo. O código recebe uma mensagem e envia de volta imediatamente a mesma mensagem. As mensagens são enviadas e recebidas em um loop até que o cliente feche a conexão:

C#

Copiar

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

Ao aceitar a conexão WebSocket antes de iniciar o loop, o pipeline de middleware é encerrado. Ao fechar o soquete, o pipeline é desenrolado. Ou seja, a solicitação deixa de avançar no pipeline quando o WebSocket é aceito. Quando o loop é concluído e o soquete é fechado, a solicitação continua a avançar no pipeline.

Tratar desconexões de cliente

O servidor não é informado automaticamente quando o cliente se desconecta devido à perda de conectividade. O servidor recebe uma mensagem de desconexão apenas quando o cliente a envia, e isso é possível somente quando há conexão com a Internet. Se quiser tomar alguma medida quando isso ocorrer, defina um tempo limite, caso não receba nada do cliente após uma determinada janela de tempo.

Se o cliente não envia mensagens com frequência, e você prefere não definir um tempo limite apenas porque a conexão fica ociosa, peça ao cliente para usar um temporizador a fim de enviar uma mensagem de ping a cada X segundos. No servidor, se uma mensagem não chegar dentro de 2*X segundos após a mensagem anterior, encerre a conexão e informe que o cliente se desconectou. Aguarde o dobro do intervalo de tempo esperado a fim de deixar um tempo extra para atrasos na rede, que possam atrasar a mensagem de ping.

Restrição de origem do WebSocket

As proteções fornecidas pelo CORS não se aplicam ao WebSockets. Navegadores não:

  • Executam solicitações de simulação de CORS.
  • Respeitam as restrições especificadas em cabeçalhos Access-Control ao fazer solicitações de WebSocket.

No entanto, os navegadores enviam o cabeçalho Origin ao emitir solicitações de WebSocket. Os aplicativos devem ser configurados para validar esses cabeçalhos e garantir que apenas WebSockets provenientes de origens esperadas sejam permitidos.

Se você estiver hospedando o servidor em "https://server.com" e hospedando seu cliente em "https://client.com", adicione "https://client.com" à lista AllowedOrigins para o WebSockets verificar.

C#

Copiar

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

app.UseWebSockets(webSocketOptions);

 Observação


O cabeçalho Origin é controlado pelo cliente e, como o cabeçalho Referer, pode ser falsificado. Não use esses cabeçalhos como um mecanismo de autenticação.

Suporte ao IIS/IIS Express

O Windows Server 2012 ou posterior e o Windows 8 ou posterior com o IIS/IIS Express 8 ou posterior são compatíveis com o protocolo WebSocket.

 Observação


WebSockets estão sempre habilitados ao usar o IIS Express.

Habilitar WebSockets no IIS

Para habilitar o suporte para o protocolo WebSocket no Windows Server 2012 ou posterior:

 Observação


Estas etapas não são necessárias ao usar o IIS Express

  1. Use o assistente Adicionar Funções e Recursos por meio do menu Gerenciar ou do link no Gerenciador do Servidor.
  2. Selecione Instalação baseada em função ou em recurso. Selecione Avançar.
  3. Selecione o servidor apropriado (o servidor local é selecionado por padrão). Selecione Avançar.
  4. Expanda Servidor Web (IIS) na árvore Funções, expanda Servidor Web e, em seguida, expanda Desenvolvimento de Aplicativos.
  5. Selecione o Protocolo WebSocket. Selecione Avançar.
  6. Se não forem necessários recursos adicionais, selecione Avançar.
  7. Selecione Instalar.
  8. Quando a instalação for concluída, selecione Fechar para sair do assistente.

Para habilitar o suporte para o protocolo WebSocket no Windows 8 ou posterior:

 Observação


Estas etapas não são necessárias ao usar o IIS Express

  1. Navegue Painel de Controle Programas e Recursos Windows > > > ativar ou desativar (lado esquerdo da tela).
  2. Abra os seguintes nós: Serviços de Informações da Internet World Wide Web desenvolvimento de > > aplicativos do Services.
  3. Selecione o recurso Protocolo WebSocket. Selecione OK.

Desabilite o WebSocket ao usar o socket.io no Node.js

Se estiver usando o suporte do WebSocket no socket.io no Node.js, desabilite o módulo WebSocket do IIS padrão usando o elemento noweb.configwebSocket ou applicationHost.config. Se essa etapa não for executada, o módulo WebSocket do IIS tentará lidar com a comunicação do WebSocket em vez de Node.js e o aplicativo.

XML

Copiar

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

Aplicativo de exemplo

aplicativo de exemplo que acompanha este artigo é um aplicativo de eco. Ele tem uma página da Web que faz conexões WebSocket e o servidor resende todas as mensagens recebidas de volta ao cliente. O aplicativo de exemplo não está configurado para ser executado do Visual Studio com IIS Express, portanto, execute o aplicativo em um shell de comando com e navegue em um dotnet run navegador para http://localhost:5000 . A página da Web mostra o status da conexão:

Estado inicial da página da Web antes da conexão webSockets

Selecione Conectar para enviar uma solicitação WebSocket para a URL exibida. Insira uma mensagem de teste e selecione Enviar. Quando terminar, selecione Fechar Soquete. A seção Log de Comunicação relata cada ação de abertura, envio e fechamento conforme ela ocorre.

Estado final da página da Web depois que as mensagens de teste e conexão webSockets são enviadas e recebidas

0
0

Comentários (1)

0
Leandro Carvalho

Leandro Carvalho

20/08/2021 17:23

Parabéns pelo excelente Artigo.

alfredo gelk neto

Brasil