【发布时间】:2018-06-22 10:02:36
【问题描述】:
我用 VS2017 创建了一个 Asp.net Core 2.1 项目,并配置了一个 linux Docker 容器。
我想实现 websockets,所以我完全遵循了这个文档:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/websockets?view=aspnetcore-2.1
如果我将 ASP.net 项目设置为启动项目(使用 IIS express),那么一切正常,我可以使用 chrome Smart Websocket Client 扩展名连接到 websocket 端点。
但是,如果我将 Docker-compose 项目设置为启动项目(因此应用程序在 linux 容器上运行),那么当我尝试连接到 websocket 端点时,服务器上会出现异常。
知道为什么这适用于 IIS express 而不是 Docker linux 容器吗?
这是一个例外:
Failed to authenticate HTTPS connection.
System.IO.IOException: The handshake failed due to an unexpected packet format.
at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Security.SslState.ThrowIfExceptional()
at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
at System.Net.Security.SslStream.EndAuthenticateAsServer(IAsyncResult asyncResult)
at System.Net.Security.SslStream.<>c.<AuthenticateAsServerAsync>b__51_1(IAsyncResult iar)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionAdapter.InnerOnConnectionAsync(ConnectionAdapterContext context)
HttpsConnectionAdapter:Debug: Failed to authenticate HTTPS connection.
System.IO.IOException: The handshake failed due to an unexpected packet format.
at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Security.SslState.ThrowIfExceptional()
at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
at System.Net.Security.SslStream.EndAuthenticateAsServer(IAsyncResult asyncResult)
at System.Net.Security.SslStream.<>c.<AuthenticateAsServerAsync>b__51_1(IAsyncResult iar)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionAdapter.InnerOnConnectionAsync(ConnectionAdapterContext context)
更新 1:
以下是有关我如何创建项目的更多详细信息:
在 VS2017 中:
- 文件 -> 新项目 -> ASP.NET Core Web 应用程序
- 选择核心 2.1
- 选择 API
- 在 Linux 操作系统中启用 Docker 支持
- 点击确定
在 Configure(...) 的 Startup.cs 中添加以下代码:
var webSocketOptions = new WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(120),
ReceiveBufferSize = 4 * 1024
};
app.UseWebSockets(webSocketOptions);
app.Use(async (context, next) =>
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
await Echo(context, webSocket);
}
else
{
context.Response.StatusCode = 400;
}
}
else
{
await next();
}
});
在 Startup.cs 我添加以下函数
private async Task Echo(HttpContext context, WebSocket webSocket)
{
var buffer = new byte[1024 * 4];
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}
- 当我启动应用程序 (iis express) 时,经典 API 使用 HTTP 工作,Websocket 也是如此。
- 当我启动 docker 版本时,经典 API 使用 HTTP 而不是 websocket 工作(返回上述错误)。 -> 另一个我必须调查的错误。
我尝试在项目调试属性中激活 SSL:
- 然后当我启动应用程序 (iis express) 时,经典 API 使用 HTTPS 工作,但 websocket 挂起(服务器端没有收到任何内容)。
- 当我启动 docker 版本时,经典 API 使用 HTTPS 而不是 websocket 工作(返回上述错误)。
【问题讨论】:
-
异常显示 HTTPS 连接失败,这与 WebSocket 没有紧密联系。您可以检查它是否已报告给 Microsoft,github.com/dotnet/corefx/issues 或在那里发布一个包含更多详细信息的新问题。
-
嗨@LexLi,我在原帖中添加了更多细节。我不知道为什么这是一个 HTTPS 错误,因为我的项目没有使用 SSL,我使用经典的 HTTP 端口来调用 web api 和 websocket。
标签: c# linux docker asp.net-core websocket