问题描述
我需要将websocket功能添加到旧版asp.net Webforms应用程序中(只是从旧的applet功能转换而来的一个简单的长期工作流程)。
我天真地尝试将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放在单独的应用程序/服务器上,但希望将其放置在可以访问同一会话对象的位置。
解决方法
应该可以在经典的ASP.NET Forms应用程序中处理Web套接字连接。这些工具在HttpContext
上可用,并且您基本上有正确的想法。
我认为问题在于您试图从 aspx 页调用它,而不仅仅是使用通用的IHttpHandler
。 IIS根据文件扩展名运行特定的处理管道。 Aspx 专门用于尝试呈现HTML页面,因此虽然可以重新配置IIS以允许WebSocket与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,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;
}
}
}
您现在应该可以连接到网络套接字了。请注意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处理程序访问会话数据。您的会话可能会在网络套接字使用期限之外过期。您可能想要使用其他机制在套接字和页面的其余部分(可能是数据库或应用程序级缓存)之间保持状态,您可以在上面的示例中从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;
}
}
}