c# - WCF websocket 在断开连接时不会关闭

标签 c# wcf

我正在尝试在 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/

相关文章:

c# - 如何解析 XSD 文件

c# - 多线程 Web 应用程序

c# - 在 ExecuteStoreQuery 错误消息 : "Value does not fall within the expected range." 中使用 OracleParameter

WCF:找不到我在 web.config 中指定的自定义验证器 - customUserNamePasswordValidatorType - - 无法加载文件或程序集... - 帮助?

c# - HTTP 请求未经客户端身份验证方案 'Ntlm' 授权。从服务器收到的身份验证 header 是 'Negotiate,NTLM'

c# - 在 C# 中计算值的数组(从 Excel 转换公式)

c# - 访问实例变量时使用关键字this是不是效率更高?

wcf - WebHttpBinding 安全问题

wcf - 我遇到 WCF 服务错误 ....Found 节点类型 'Element',名称为“tns :downloadOrders”

wcf - WCF 中的大请求问题