【问题标题】:How to work with System.Net.WebSockets without ASP.NET?如何在没有 ASP.NET 的情况下使用 System.Net.WebSockets?
【发布时间】:2015-08-09 23:48:42
【问题描述】:

我想在 .NET 4.5 及更高版本(在 Windows 8.1 上)中使用新的 System.Net.WebSockets 类实现一个简单的聊天服务器。但是,我只找到在 ASP.NET 环境中使用这些类的示例(尤其是这里的那些:http://www.codemag.com/Article/1210051

我没有这样的协议,并且希望尽可能“原始”地实现 websocket 服务器,但不必像微软希望在 .NET 4.5 中那样重新实现所有 websocket 协议。

我想像使用普通的Socket 一样简单地实例化一个新的WebSocket 类,但是构造函数是受保护的。所以我去创建一个继承自它的类,但后来我注意到我必须实现这么多抽象方法和属性,看起来我正在重写整个逻辑(特别是因为我必须实现像 State 或 @ 987654330@)。

恐怕 MSDN 文档对我没有帮助。那里的文档处于预发布状态,许多 cmets 只是说“待定”或“何时实施”。

【问题讨论】:

标签: c# .net websocket


【解决方案1】:

是的。

最简单的方法是使用 HTTPListener。如果你搜索 HTTPListener WebSocket,你会发现很多例子。

简而言之(伪代码)

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

需要 .NET 4.5 和 Windows 8 或更高版本。

【讨论】:

    【解决方案2】:

    我偶然发现了this link,它展示了如何仅使用System.Net.WebSockets 实现来实现IHttpHandler。该处理程序是必需的,因为 .NET WebSocket 实现依赖于 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<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; }
            }
        }
    }
    

    希望对您有所帮助!

    【讨论】:

      【解决方案3】:

      Ian 的回答肯定很好,但我需要一个循环过程。互斥锁对我来说很关键。这是一个基于他的工作.net core 2 示例。我无法谈论这个循环的可扩展性。

      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(string[] 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<byte>(Encoding.UTF8.GetBytes("Hello world")),
                              WebSocketMessageType.Text, true, CancellationToken.None);
                      }
                  }
                  signal.ReleaseMutex();
              }
          }
      }
      

      还有一个测试 html 页面。

      <!DOCTYPE html>
        <meta charset="utf-8" />
        <title>WebSocket Test</title>
        <script language="javascript" type="text/javascript">
      
        var wsUri = "ws://localhost:8080/";
        var output;
      
        function init()
        {
          output = document.getElementById("output");
          testWebSocket();
        }
      
        function testWebSocket()
        {
          websocket = new WebSocket(wsUri);
          websocket.onopen = function(evt) { onOpen(evt) };
          websocket.onclose = function(evt) { onClose(evt) };
          websocket.onmessage = function(evt) { onMessage(evt) };
          websocket.onerror = function(evt) { onError(evt) };
        }
      
        function onOpen(evt)
        {
          writeToScreen("CONNECTED");
          doSend("WebSocket rocks");
        }
      
        function onClose(evt)
        {
          writeToScreen("DISCONNECTED");
        }
      
        function onMessage(evt)
        {
          writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
        }
      
        function onError(evt)
        {
          writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
        }
      
        function doSend(message)
        {
          writeToScreen("SENT: " + message);
          websocket.send(message);
        }
      
        function writeToScreen(message)
        {
          var pre = document.createElement("p");
          pre.style.wordWrap = "break-word";
          pre.innerHTML = message;
          output.appendChild(pre);
        }
      
        window.addEventListener("load", init, false);
      
        </script>
      
        <h2>WebSocket Test</h2>
      
        <div id="output"></div>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-23
        • 2017-03-14
        • 1970-01-01
        • 2018-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-30
        相关资源
        最近更新 更多