我目前正致力于在ASP.NET 5(DNX),DNX Core Console和通用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 CAN会从UWP应用程序中接收数据,只是WebSockets似乎有问题。
注意:我想重新使用System.Net.WebSockets.Client,因为我要将所有内容都放在共享库中。
我有一个可行的最小解决方案,可以在我的OneDrive上重现这个问题:https://onedrive.live.com/redir?resid=1DDFA1793BD83CB5!270551&authkey=!AFtXc_Xae2qnpF8&ithint=file%2czip
非常感谢帮助;提前谢谢!
答案 0 :(得分:1)
在System.Net.WebSockets.Client
中,它为不同的平台使用不同的WebSocketHandle
。查看GitHub和WebSocketHandle.WinRT.cs
中的源代码,您可以发现其_webSocket
定义为WinRTWebSocket
。在WinRTWebSocket
中,它使用MessageWebSocket
建立连接并接收数据。 MessageWebSocket
是我们通常在UWP应用程序中使用的WebSocket类。 MessageWebSocket
使用MessageReceived
事件来处理收到的消息。此事件通知用户任何传入的消息。但是,当端点收到整个消息时,将调用此事件(而不是部分片段)。
因此,当您使用endOfMessage
方法将WebSocket.SendAsync
参数发送到false
时,MessageReceived
事件将被调用,因为消息未完成。您可以使用MessageWebSocket
构建一个UWP项目来测试它(您可以参考WebSocket sample in GitHub)。这使Socket.ReceiveAsync
方法总是等待,你觉得没有收到数据。
要解决此问题,您需要在消息结束时将endOfMessage
方法中的WebSocket.SendAsync
参数设置为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!
。