WebSocket em C#: projetos reais e técnicas avançadas

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

WebSocket em C#: do protótipo à produção — técnicas avançadas de aplicações em tempo real

\n\n

A implementação padrão de WebSocket em C# usando bibliotecas como System.Net.WebSockets ou SignalR resolve tarefas básicas de chats e notificações. No entanto, quando os requisitos vão além do "Hello, World", o desenvolvedor se depara com a necessidade de escalabilidade, segurança, roteamento personalizado e otimização de desempenho. Neste artigo, abordaremos técnicas avançadas de trabalho com WebSocket no .NET que permitirão construir sistemas de tempo real robustos e de alta carga.

\n\n

1. Arquitetura de servidor WebSocket escalável: padrões e clusterização

\n\n

Uma das principais limitações do WebSocket padrão é a vinculação da conexão a uma instância específica do processo. Ao escalar horizontalmente, uma mensagem enviada ao servidor A não alcançará o cliente conectado ao servidor B. Para resolver esse problema, são usadas duas abordagens:

\n\n
    \n
  • Backplane centralizado: Uso de Redis Pub/Sub, RabbitMQ ou Azure SignalR Service para troca de mensagens entre servidores.
  • \n
  • Sessões persistentes (Sticky Sessions): O balanceador direciona as requisições do cliente sempre para o mesmo servidor. Método menos confiável, pois, se o nó cair, todos os seus clientes perdem a conexão.
  • \n
\n\n

Vejamos um exemplo de implementação de um backplane personalizado no Redis usando StackExchange.Redis e System.Net.WebSockets.

\n\n
using StackExchange.Redis;\nusing System.Net.WebSockets;\nusing System.Text;\n\npublic class RedisBackplaneManager\n{\n    private readonly ConnectionMultiplexer _redis;\n    private readonly ISubscriber _subscriber;\n    private readonly ConcurrentDictionary<string, WebSocket> _connections;\n\n    public RedisBackplaneManager(string redisConnectionString)\n    {\n        _redis = ConnectionMultiplexer.Connect(redisConnectionString);\n        _subscriber = _redis.GetSubscriber();\n        _connections = new ConcurrentDictionary<string, WebSocket>();\n        \n        // Inscrevemos no canal "websocket:messages"\n        _subscriber.Subscribe("websocket:messages", (channel, message) => {\n            var data = Encoding.UTF8.GetString(message);\n            // Analisamos a mensagem (assumimos formato: "connectionId:payload")\n            var parts = data.Split(':', 2);\n            if (parts.Length == 2 && _connections.TryGetValue(parts[0], out var ws))\n            {\n                ws.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(parts[1])), \n                    WebSocketMessageType.Text, true, CancellationToken.None);\n            }\n        });\n    }\n\n    public async Task SendToClientAsync(string connectionId, string message)\n    {\n        // Publicamos no Redis para que a mensagem seja recebida por todos os servidores\n        var payload = $"{connectionId}:{message}";\n        await _subscriber.PublishAsync("websocket:messages", payload);\n    }\n\n    public void AddConnection(string id, WebSocket ws) => _connections.TryAdd(id, ws);\n    public void RemoveConnection(string id) => _connections.TryRemove(id, out _);\n}
\n\n

2. Protocolo personalizado e roteamento: WebSocket como transporte RPC

\n\n

Frequentemente, não é necessário apenas enviar texto, mas sim chamar procedimentos remotos (RPC) via WebSocket. Em vez de analisar manualmente JSON e verificar comandos, podemos construir um roteador de mensagens minimalista. Essa abordagem é usada internamente pelo SignalR, mas você pode implementá-la para ter controle total.

\n\n
public class WebSocketRouter\n{\n    private readonly Dictionary<string, Func<string, Task>> _routes = new();\n\n    public void On(string action, Func<string, Task> handler)\n    {\n        _routes[action] = handler;\n    }\n\n    public async Task RouteAsync(string rawMessage)\n    {\n        // Esperamos o formato                

Blogs

Book Recommendations