【问题标题】:Using websockets in classic asp.net forms application在经典的 asp.net 表单应用程序中使用 websockets
【发布时间】:2020-10-08 09:35:00
【问题描述】:

我需要将 websocket 功能添加到旧的 asp.net webforms 应用程序(只是从旧的小程序功能转换而来的一个简单的长时间工作流)。

我天真地试图将 websocket 处理程序添加到 aspx 页面:

        public override void ProcessRequest(HttpContext context)
        {
            if (context.IsWebSocketRequest)
            {
                context.AcceptWebSocketRequest(HandleWebSocket);
            } else
            {
                base.ProcessRequest(context);
            }
        }

并在 IIS 上启用 websocket: 那就试试吧:var ws = new WebSocket("ws://localhost/APP/Page.aspx"); 但这似乎不起作用。

不确定这是否可能?

我是否错过了有关配置或实施的一些内容? 我可以将 websocket 放在单独的应用程序/服务器上,但更愿意将它保存在一个可以访问相同会话对象的地方。

【问题讨论】:

  • 你使用 IIS 8.0 吗?

标签: c# asp.net websocket asp.net-4.5


【解决方案1】:

应该可以在经典的 ASP.NET Forms 应用程序中处理 Web 套接字连接。这些工具在HttpContext 上可用,您基本上有正确的想法。

我认为问题在于您试图从 aspx 页面调用它,而不仅仅是使用通用 IHttpHandler。 IIS 基于文件扩展名运行特定的处理管道。 Aspx 专门用于尝试呈现 HTML 页面,因此虽然可以重新配置 IIS 以允许 websockets 与 ASPX 页面交互,但使用通用 ashx 更容易 处理程序。

您可以通过转到 Visual Studio 中的“添加项目”对话框来创建处理程序

此时,您只需在处理程序代码中实现您的 websocket 逻辑。我在this aspnet sample 中添加一个简单的回声只是为了演示。

public class MyHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        if (context.IsWebSocketRequest)
        {
            context.AcceptWebSocketRequest(EchoWebSocket);
        }
    }

    private async Task EchoWebSocket(AspNetWebSocketContext socketContext)
    {
        var buffer = new byte[1024 * 4];
        var result = await socketContext.WebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

        while (!result.CloseStatus.HasValue)
        {
            await socketContext.WebSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
            result = await socketContext.WebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
        }

        await socketContext.WebSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
    }

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

您现在应该能够连接到 websocket。注意wss 的用法,而不是ws。我测试的设置需要安全版本(wss)。使用与您正在处理的应用程序相关的任何内容。

// Replace with port/path to your handler.
var ws = new WebSocket("wss://localhost:44336/MyHandler.ashx");

ws.onmessage = function(evt) { 
    console.log(evt); 
};

ws.send("Hello, World!");

您应该会看到与此类似的输出:

注意:我通常不建议尝试从 websocket 处理程序访问 Session 数据。您的会话可能会在 websocket 的生命周期之外过期。您可能希望使用其他机制在套接字和其余页面(可能是数据库或应用程序级缓存,您可以在上面的示例中从socketContext.Cache 访问)之间保持状态。

编辑:添加了在套接字初始化时使用会话值的示例。 根据您的评论,如果您想在 websocket 的 初始化 期间使用会话值(这应该是一个安全的操作),那么您的处理程序只需要实现 IRequiresSessionState 并需要添加一些额外的将会话值传递给接受处理程序的语法。

public class MyHandler : IHttpHandler, IRequiresSessionState
{
    public void ProcessRequest(HttpContext context)
    {
        if (context.IsWebSocketRequest)
        {
            var sessionValue = context.Session["session_key"] as string;

            context.AcceptWebSocketRequest(async (socketContext) =>
            {
                await SetupWebSocket(socketContext, sessionValue);
            });
        }
    }

    private async Task SetupWebSocket(AspNetWebSocketContext socketContext, string sessionValue)
    {
        // Handle socket as before, but 'sessionValue' is now available for use.
    }

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

【讨论】:

  • 谢谢,aspx 是这里的问题。
  • 我只需要 session 来初始化 websocket,session 本身不适用于处理函数,因为它不是线程安全的。
  • @tester.one 好的。这个用例是有道理的。我添加了另一个示例来演示如何做到这一点。
猜你喜欢
  • 1970-01-01
  • 2014-06-03
  • 1970-01-01
  • 1970-01-01
  • 2011-11-03
  • 1970-01-01
  • 1970-01-01
  • 2010-12-07
  • 2011-07-22
相关资源
最近更新 更多