我正在尝试在 C# 中使用自托管网络套接字。基本上我当前的测试工作正常,但是当客户端关闭 websocket 时,代码仍在尝试发送数据。 我想念什么吗?是否有更好的(内置)方法来处理 websockets?
(我正在使用 .Net Framework 4.8)
using System;
using System.Net.WebSockets;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Text;
using System.Threading.Tasks;
namespace WebSocketTest
{
[ServiceContract]
public interface ITestWebSocketCallback
{
[OperationContract(IsOneWay = true, Action = "*")]
Task SendResult(Message msg);
}
[ServiceContract(CallbackContract = typeof(ITestWebSocketCallback))]
public interface ITestWebSocket
{
[OperationContract(IsOneWay = true, Action = "*")]
Task StartSending(Message msg);
}
public class TestWebSocket : ITestWebSocket
{
public async Task StartSending(Message msg)
{
Console.WriteLine("Started sending");
var callback = OperationContext.Current.GetCallbackChannel<ITestWebSocketCallback>();
try
{
var random = new Random();
var result = 100.00;
while (((IChannel)callback).State == CommunicationState.Opened)
{
await callback.SendResult(CreateMessage($"{result}"));
result += random.NextDouble();
await Task.Delay(1000);
}
Console.WriteLine("Channel closed");
}
catch (WebSocketException wse)
{
Console.WriteLine($"WebSocketException: {wse.Message}");
}
catch (Exception e)
{
Console.WriteLine($"Exception: {e.Message}");
}
Console.WriteLine("Finished sending");
}
Message CreateMessage(string msgText)
{
var msg = ByteStreamMessage.CreateMessage(new ArraySegment<byte>(Encoding.UTF8.GetBytes(msgText)));
msg.Properties["WebSocketMessageProperty"] = new WebSocketMessageProperty
{
MessageType = WebSocketMessageType.Text
};
return msg;
}
}
static class Program
{
static void Main(string[] args)
{
var baseAddress = new Uri("http://localhost:8080/TestWS");
// Create the ServiceHost.
var _host = new ServiceHost(typeof(TestWebSocket), baseAddress);
//// Enable metadata publishing.
var behaviour = new ServiceMetadataBehavior();
behaviour.HttpGetEnabled = true;
behaviour.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
_host.Description.Behaviors.Add(behaviour);
// Create WebSocket
var binding = new CustomBinding();
binding.Elements.Add(new ByteStreamMessageEncodingBindingElement());
var transport = new HttpTransportBindingElement();
transport.WebSocketSettings.TransportUsage = WebSocketTransportUsage.Always;
transport.WebSocketSettings.CreateNotificationOnConnection = true;
binding.Elements.Add(transport);
_host.AddServiceEndpoint(typeof(ITestWebSocket), binding, "");
// Open the ServiceHost to start listening for messages.
Console.WriteLine("Opening websocket...");
try
{
_host.Open();
Console.WriteLine("Opened!");
Console.WriteLine(baseAddress);
}
catch (Exception e)
{
Console.WriteLine($"Cannot open: {e.Message}");
throw;
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
}
}
除了输出有点像:
Started sending
Channel closed
Finished sending
但我得到:
Started sending
WebSocketException
Finished sending
最佳答案
据我所知,这是不可能的。官方文档中提到(双工通信等同于websocket,因为WCF是使用websocket协议(protocol)实现双工通信的)。
The duplex model doesn't automatically detect when a service or client closes its channel. So if a client unexpectedly terminates, by default the service will not be notified, or if a service unexpectedly terminates, the client will not be notified. If you use a service that is disconnected, the CommunicationException exception is raised. Clients and services can implement their own protocol to notify each other if they so choose. For more information on error handling, see WCF Error Handling
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/duplex-services
在我看来,我们可以发送一个心跳包来证明客户端是活的,或者我们可以定义和实现另一个服务契约,或者使用下面的OperationContext等。
OperationContext.Current.Channel.Faulted += delegate
{
Console.WriteLine("");
};
关于c# - WCF websocket 在断开连接时不会关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56847603/