Windows Store (UWP) / .NET Core / DNX WebSockets 无法传输数据
Windows Store (UWP) / .NET Core / DNX WebSockets unable to transfer data
我目前正在研究一种在 ASP.NET 5 (DNX)、DNX 核心控制台和通用 Windows 平台(Windows 商店)应用程序之间创建 WebSocket 连接的方法.
ASP.NET 5 作为服务器使用包 "Microsoft.AspNet.WebSockets.Server": "1.0.0-rc1-final"。
控制台应用程序和 UWP 应用程序都使用 "System.Net.WebSockets.Client": "4.0.0-beta-23516" 作为 websocket 服务器。
服务器配置方法使用以下方法设置了一个非常简单的 WebSocket 服务器:
app.UseWebSockets();
app.Use( async ( Context, Next ) =>
{
var HttpContext = ( HttpContext )Context;
if( HttpContext.WebSockets.IsWebSocketRequest )
{
WebSocket Socket = await HttpContext.WebSockets.AcceptWebSocketAsync();
await Task.Delay( 100 );
CancellationTokenSource Cts = new CancellationTokenSource();
CancellationToken Ct = Cts.Token;
System.Diagnostics.Debug.WriteLine( "New client; sending data..." );
byte[] Data = System.Text.Encoding.UTF8.GetBytes( "Hello WebSocket!" );
await Socket.SendAsync( new ArraySegment<byte>( Data ), WebSocketMessageType.Binary, false, Ct );
System.Diagnostics.Debug.WriteLine( "Data sent." );
//System.Diagnostics.Debug.WriteLine( "New client; receiving data..." );
//byte[] Data = new byte[ 16 ];
//var Result = await Socket.ReceiveAsync( new ArraySegment<byte>( Data ), Ct );
//System.Diagnostics.Debug.WriteLine( $"Data received: {Result.Count}" );
}
} );
两个客户端(控制台和 UWP 应用程序)都使用以下代码连接到服务器:
CancellationTokenSource Cts = new CancellationTokenSource();
CancellationToken Ct = Cts.Token;
string Address = "ws://localhost:5000";
var Socket = new System.Net.WebSockets.ClientWebSocket();
Console.WriteLine( $"Creating connection to: {Address}" );
await Socket.ConnectAsync( new Uri( Address ), Ct );
Task.Delay( 100 ).Wait();
byte[] Data = new byte[ 1024 ];
Console.WriteLine( "Receiving data..." );
var Result = await Socket.ReceiveAsync( new ArraySegment<byte>( Data ), Ct );
Console.WriteLine( $"Data received: {Result.Count}" );
//Console.WriteLine( "Sending data..." );
//byte[] Data = System.Text.Encoding.UTF8.GetBytes( "Hello WebSocket!" );
//Socket.SendAsync( new ArraySegment<byte>( Data ), WebSocketMessageType.Binary, false, Ct ).Wait();
//Console.WriteLine( "Data sent." );
(当然,UWP 应用程序不使用 Console.WriteLine,而是写入文本块。
当 运行 服务器和控制台应用程序时,通信正常(发送和接收数据)。但是,当 运行 UWP 应用程序时,已建立连接但未收到任何数据。我已经尝试过相反的方式(因此是注释行),在这种情况下,UWP 应用程序确实发送了数据,但服务器没有收到它...
这是某个实现中的错误还是我做错了什么?我已经尝试在另一台机器上部署服务器并检查了我的环回异常——结果相同。
在服务器应用程序中使用 MVC 时,HttpClient 可以从 UWP 应用程序中接收数据,只是 WebSockets 似乎是个问题。
注意:我想重新使用 System.Net.WebSockets.Client 因为我要把所有东西都放在共享库中。
我有一个最小的工作解决方案来在我的 OneDrive 上重现该问题:https://onedrive.live.com/redir?resid=1DDFA1793BD83CB5!270551&authkey=!AFtXc_Xae2qnpF8&ithint=file%2czip
非常感谢您的帮助;提前致谢!
在System.Net.WebSockets.Client
中,针对不同的平台使用不同的WebSocketHandle
。查看源码GitHub and in WebSocketHandle.WinRT.cs
, you can find its _webSocket
is defined as WinRTWebSocket
. In WinRTWebSocket
, it uses MessageWebSocket
to establish connection and receive data. MessageWebSocket
就是我们在UWP应用中常用的WebSocketclass。 MessageWebSocket
使用 MessageReceived
事件来处理收到的消息。此事件通知用户任何传入消息。但是当端点接收到整个消息时调用此事件(不是部分片段)。
因此,当您在 WebSocket.SendAsync
方法中使用 endOfMessage
参数向 false
发送数据时,MessageReceived
事件不会被调用,因为消息不完整。您可以使用 MessageWebSocket
构建一个 UWP 项目来测试它(您可以参考 WebSocket sample in GitHub)。这使得 Socket.ReceiveAsync
方法总是等待,你感觉没有收到数据。
要解决此问题,需要在消息结束时将WebSocket.SendAsync
方法中的endOfMessage
参数设置为true
。例如在您的服务器中使用以下代码:
await Socket.SendAsync(new ArraySegment<byte>(Data), WebSocketMessageType.Binary, false, Ct);
await Task.Delay(1000);
await Socket.SendAsync(new ArraySegment<byte>(Data), WebSocketMessageType.Binary, true, Ct);
然后在你的客户端你会收到Hello WebSocket!Hello WebSocket!
.
我目前正在研究一种在 ASP.NET 5 (DNX)、DNX 核心控制台和通用 Windows 平台(Windows 商店)应用程序之间创建 WebSocket 连接的方法.
ASP.NET 5 作为服务器使用包 "Microsoft.AspNet.WebSockets.Server": "1.0.0-rc1-final"。 控制台应用程序和 UWP 应用程序都使用 "System.Net.WebSockets.Client": "4.0.0-beta-23516" 作为 websocket 服务器。
服务器配置方法使用以下方法设置了一个非常简单的 WebSocket 服务器:
app.UseWebSockets();
app.Use( async ( Context, Next ) =>
{
var HttpContext = ( HttpContext )Context;
if( HttpContext.WebSockets.IsWebSocketRequest )
{
WebSocket Socket = await HttpContext.WebSockets.AcceptWebSocketAsync();
await Task.Delay( 100 );
CancellationTokenSource Cts = new CancellationTokenSource();
CancellationToken Ct = Cts.Token;
System.Diagnostics.Debug.WriteLine( "New client; sending data..." );
byte[] Data = System.Text.Encoding.UTF8.GetBytes( "Hello WebSocket!" );
await Socket.SendAsync( new ArraySegment<byte>( Data ), WebSocketMessageType.Binary, false, Ct );
System.Diagnostics.Debug.WriteLine( "Data sent." );
//System.Diagnostics.Debug.WriteLine( "New client; receiving data..." );
//byte[] Data = new byte[ 16 ];
//var Result = await Socket.ReceiveAsync( new ArraySegment<byte>( Data ), Ct );
//System.Diagnostics.Debug.WriteLine( $"Data received: {Result.Count}" );
}
} );
两个客户端(控制台和 UWP 应用程序)都使用以下代码连接到服务器:
CancellationTokenSource Cts = new CancellationTokenSource();
CancellationToken Ct = Cts.Token;
string Address = "ws://localhost:5000";
var Socket = new System.Net.WebSockets.ClientWebSocket();
Console.WriteLine( $"Creating connection to: {Address}" );
await Socket.ConnectAsync( new Uri( Address ), Ct );
Task.Delay( 100 ).Wait();
byte[] Data = new byte[ 1024 ];
Console.WriteLine( "Receiving data..." );
var Result = await Socket.ReceiveAsync( new ArraySegment<byte>( Data ), Ct );
Console.WriteLine( $"Data received: {Result.Count}" );
//Console.WriteLine( "Sending data..." );
//byte[] Data = System.Text.Encoding.UTF8.GetBytes( "Hello WebSocket!" );
//Socket.SendAsync( new ArraySegment<byte>( Data ), WebSocketMessageType.Binary, false, Ct ).Wait();
//Console.WriteLine( "Data sent." );
(当然,UWP 应用程序不使用 Console.WriteLine,而是写入文本块。 当 运行 服务器和控制台应用程序时,通信正常(发送和接收数据)。但是,当 运行 UWP 应用程序时,已建立连接但未收到任何数据。我已经尝试过相反的方式(因此是注释行),在这种情况下,UWP 应用程序确实发送了数据,但服务器没有收到它...
这是某个实现中的错误还是我做错了什么?我已经尝试在另一台机器上部署服务器并检查了我的环回异常——结果相同。 在服务器应用程序中使用 MVC 时,HttpClient 可以从 UWP 应用程序中接收数据,只是 WebSockets 似乎是个问题。
注意:我想重新使用 System.Net.WebSockets.Client 因为我要把所有东西都放在共享库中。
我有一个最小的工作解决方案来在我的 OneDrive 上重现该问题:https://onedrive.live.com/redir?resid=1DDFA1793BD83CB5!270551&authkey=!AFtXc_Xae2qnpF8&ithint=file%2czip
非常感谢您的帮助;提前致谢!
在System.Net.WebSockets.Client
中,针对不同的平台使用不同的WebSocketHandle
。查看源码GitHub and in WebSocketHandle.WinRT.cs
, you can find its _webSocket
is defined as WinRTWebSocket
. In WinRTWebSocket
, it uses MessageWebSocket
to establish connection and receive data. MessageWebSocket
就是我们在UWP应用中常用的WebSocketclass。 MessageWebSocket
使用 MessageReceived
事件来处理收到的消息。此事件通知用户任何传入消息。但是当端点接收到整个消息时调用此事件(不是部分片段)。
因此,当您在 WebSocket.SendAsync
方法中使用 endOfMessage
参数向 false
发送数据时,MessageReceived
事件不会被调用,因为消息不完整。您可以使用 MessageWebSocket
构建一个 UWP 项目来测试它(您可以参考 WebSocket sample in GitHub)。这使得 Socket.ReceiveAsync
方法总是等待,你感觉没有收到数据。
要解决此问题,需要在消息结束时将WebSocket.SendAsync
方法中的endOfMessage
参数设置为true
。例如在您的服务器中使用以下代码:
await Socket.SendAsync(new ArraySegment<byte>(Data), WebSocketMessageType.Binary, false, Ct);
await Task.Delay(1000);
await Socket.SendAsync(new ArraySegment<byte>(Data), WebSocketMessageType.Binary, true, Ct);
然后在你的客户端你会收到Hello WebSocket!Hello WebSocket!
.