Comment travailler avec System.Net.WebSockets sans ASP.NET?

Je souhaite implémenter un serveur de discussion simple avec les nouvelles classes System.Net.WebSockets dans .NET 4.5 et versions ultérieures (sous Windows 8.1). Cependant, je ne trouve que des exemples d’utilisation de ces classes dans un environnement ASP.NET (notamment ceux ici: http://www.codemag.com/Article/1210051 ).

Je n’en ai pas, et j’aimerais implémenter le serveur Websocket aussi “brut” que possible, mais sans avoir à réimplémenter tout le protocole websocket comme Microsoft l’avait déjà fait, espérons-le, dans .NET 4.5.

Je pensais simplement instancier une nouvelle classe WebSocket comme je le ferais avec un Socket normal, mais le constructeur est protégé. Je suis donc allé créer une classe qui en hérite, mais j’ai ensuite remarqué que je devais implémenter tellement de méthodes et de propriétés abstraites qu’il me semblait que je réécrivais toute la logique (surtout parce que je devais implémenter des choses comme State ou SendAsync ).

Je crains que la documentation MSDN ne m’aide pas. La documentation présente le statut de pré-publication et de nombreux commentaires se contentent de dire “à déterminer” ou “lorsqu’il sera mis en œuvre”.

Oui.

Le moyen le plus simple consiste à utiliser un HTTPListener. Si vous recherchez HTTPListener WebSocket, vous trouverez de nombreux exemples.

En bref (pseudo-code)

 HttpListener httpListener = new HttpListener(); httpListener.Prefixes.Add("http://localhost/"); httpListener.Start(); HttpListenerContext context = await httpListener.GetContextAsync(); if (context.Request.IsWebSocketRequest) { HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(null); WebSocket webSocket = webSocketContext.WebSocket; while (webSocket.State == WebSocketState.Open) { await webSocket.SendAsync( ... ); } } 

Nécessite .NET 4.5 et Windows 8 ou version ultérieure.

Je viens de trébucher sur ce lien qui montre comment implémenter un IHttpHandler utilisant uniquement l’implémentation System.Net.WebSockets . Le gestionnaire est requirejs car l’implémentation .NET WebSocket dépend d’IIS 8+.

 using System; using System.Web; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Net.WebSockets; namespace AspNetWebSocketEcho { public class EchoHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { if (context.IsWebSocketRequest) context.AcceptWebSocketRequest(HandleWebSocket); else context.Response.StatusCode = 400; } private async Task HandleWebSocket(WebSocketContext wsContext) { const int maxMessageSize = 1024; byte[] receiveBuffer = new byte[maxMessageSize]; WebSocket socket = wsContext.WebSocket; while (socket.State == WebSocketState.Open) { WebSocketReceiveResult receiveResult = await socket.ReceiveAsync(new ArraySegment(receiveBuffer), CancellationToken.None); if (receiveResult.MessageType == WebSocketMessageType.Close) { await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, ssortingng.Empty, CancellationToken.None); } else if (receiveResult.MessageType == WebSocketMessageType.Binary) { await socket.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "Cannot accept binary frame", CancellationToken.None); } else { int count = receiveResult.Count; while (receiveResult.EndOfMessage == false) { if (count >= maxMessageSize) { ssortingng closeMessage = ssortingng.Format("Maximum message size: {0} bytes.", maxMessageSize); await socket.CloseAsync(WebSocketCloseStatus.MessageTooLarge, closeMessage, CancellationToken.None); return; } receiveResult = await socket.ReceiveAsync(new ArraySegment(receiveBuffer, count, maxMessageSize - count), CancellationToken.None); count += receiveResult.Count; } var receivedSsortingng = Encoding.UTF8.GetSsortingng(receiveBuffer, 0, count); var echoSsortingng = "You said " + receivedSsortingng; ArraySegment outputBuffer = new ArraySegment(Encoding.UTF8.GetBytes(echoSsortingng)); await socket.SendAsync(outputBuffer, WebSocketMessageType.Text, true, CancellationToken.None); } } } public bool IsReusable { get { return true; } } } } 

J’espère que ça a aidé!

La réponse de Ian était définitivement bonne, mais j’avais besoin d’un processus en boucle. Le mutex était la clé pour moi. Voici un exemple .net de base 2 basé sur le sien. Je ne peux pas parler de l’évolutivité de cette boucle.

 using System; using System.Net; using System.Net.WebSockets; using System.Text; using System.Threading; namespace WebSocketServerConsole { public class Program { static HttpListener httpListener = new HttpListener(); private static Mutex signal = new Mutex(); public static void Main(ssortingng[] args) { httpListener.Prefixes.Add("http://localhost:8080/"); httpListener.Start(); while (signal.WaitOne()) { ReceiveConnection(); } } public static async System.Threading.Tasks.Task ReceiveConnection() { HttpListenerContext context = await httpListener.GetContextAsync(); if (context.Request.IsWebSocketRequest) { HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(null); WebSocket webSocket = webSocketContext.WebSocket; while (webSocket.State == WebSocketState.Open) { await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes("Hello world")), WebSocketMessageType.Text, true, CancellationToken.None); } } signal.ReleaseMutex(); } } } 

et une page de test HTML pour cela.

   WebSocket Test  

WebSocket Test