2015-05-27 11 views
10

Ich möchte einen einfachen Chat-Server mit den neuen System.Net.WebSockets Klassen in .NET 4.5 und höher (unter Windows 8.1) implementieren. Allerdings finde ich nur Beispiele, die diese Klassen in einer ASP.NET-Umgebung (vor allem die hier: http://www.codemag.com/Article/1210051) verwendenWie arbeite ich mit System.Net.WebSockets ohne ASP.NET?

Ich habe keine solche, und möchte den Websocket-Server als "roh" als implementieren möglich, aber ohne das gesamte Websocket-Protokoll neu implementieren zu müssen, wie es Microsoft hoffentlich schon in .NET 4.5 getan hat.

Ich dachte an die Instanziierung einer neuen WebSocket Klasse wie ich würde mit einem normalen Socket tun, aber der Konstruktor ist geschützt. Also habe ich eine Klasse erstellt, die von ihr abgeleitet ist, aber dann bemerkte ich, dass ich so viele abstrakte Methoden und Eigenschaften implementieren musste, dass es so aussah, als würde ich die ganze Logik umschreiben (besonders weil ich Dinge wie State oder SendAsync implementieren musste).

Ich habe Angst, dass die MSDN-Dokumentation mir nicht geholfen hat. Die Dokumentation dort hat einen Pre-Release-Status und viele Kommentare sagen nur "TBD" oder "wann es implementiert ist".

+0

möglich duplicate von [gibt es in C# SSL WebSocket-Client, der .net 4.0 ist?] (Http://StackOverflow.com/questions/13386604/is-there-in-c-sharp-ssl-websocket-client- that-is-net-4-0) – MethodMan

+1

Ja, es scheint, die System.Net.WebSocket-Typen sind ziemlich Context centric .. speziell das HttpContext-Objekt http://www.codeproject.com/Articles/618032/Using-WebSocket- in-NET-Part .. mit diesem gesagt, System.Net.WebSockets scheint nicht für eine Assembly für das Hosting von WebSocket-Servern bestimmt zu sein. –

+0

Hier ein paar Referenzlinks (MDN): Allgemeine Informationen - https: //developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_servers C# WebSocketServer Implementierung (verwendet keine .NET 4.5 WebSockets) https://developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_server. Ich bereite gerade das VB.NET-Codebeispiel auf .. Ich ziehe es an dort eine Weile zurück als Entwurf. Es hat keine Änderungen erhalten. –

Antwort

5

Ich bin gerade auf this link gestolpert, die zeigt, wie man eine IHttpHandler unter Verwendung nur der System.Net.WebSockets Implementierung implementiert. Der Handler ist erforderlich, da die .NET WebSocket-Implementierung von IIS 8+ abhängig ist.

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<byte>(receiveBuffer), CancellationToken.None); 

       if (receiveResult.MessageType == WebSocketMessageType.Close) 
       { 
        await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.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) 
         { 
          string closeMessage = string.Format("Maximum message size: {0} bytes.", maxMessageSize); 
          await socket.CloseAsync(WebSocketCloseStatus.MessageTooLarge, closeMessage, CancellationToken.None); 
          return; 
         } 

         receiveResult = await socket.ReceiveAsync(new ArraySegment<byte>(receiveBuffer, count, maxMessageSize - count), CancellationToken.None); 
         count += receiveResult.Count; 
        } 

        var receivedString = Encoding.UTF8.GetString(receiveBuffer, 0, count); 
        var echoString = "You said " + receivedString; 
        ArraySegment<byte> outputBuffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(echoString)); 

        await socket.SendAsync(outputBuffer, WebSocketMessageType.Text, true, CancellationToken.None); 
       } 
      } 
     } 

     public bool IsReusable 
     { 
      get { return true; } 
     } 
    } 
} 

Hoffe, es half!

8

Ja.

Der einfachste Weg ist die Verwendung eines HTTPListener. Wenn Sie nach HTTPListener WebSocket suchen, finden Sie viele Beispiele.

Auf den Punkt gebracht (Pseudocode)

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

Erfordert .NET 4.5 und Windows 8 oder höher.