Веб-розетка WCF не закрывается при отключении - PullRequest
2 голосов
/ 02 июля 2019

Я пытаюсь использовать автономные веб-сокеты в C #.В основном мой текущий тест работает, но когда клиент закрывает веб-сокет, код все еще пытается отправить данные.Я что-то пропустил?Есть ли лучший (встроенный) подход к работе с веб-сокетами?

(я использую .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();
        }
    }
}

I, за исключением вывода, что-то вроде:

Started sending
Channel closed
Finished sending

но я получаю:

Started sending
WebSocketException
Finished sending

1 Ответ

0 голосов
/ 03 июля 2019

Насколько я знаю, это невозможно.Как упомянуто в официальном документе (двусторонняя связь равна websocket, поскольку WCF обеспечивает двустороннюю связь с использованием протокола websocket).

Дуплексная модель не определяет автоматически, когда служба или клиент закрывает свой канал.Таким образом, если клиент неожиданно завершает работу, по умолчанию служба не будет уведомлена, или если служба неожиданно завершит работу, клиент не будет уведомлен.Если вы используете службу, которая отключена, возникает исключение CommunicationException.Клиенты и службы могут реализовать свой собственный протокол для уведомления друг друга, если они того пожелают.Для получения дополнительной информации об обработке ошибок см. Обработка ошибок WCF

https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/duplex-services
По моему мнению, мы могли бы отправить пакет контрольных сигналов, чтобы доказать, что клиент работает, или мы могли бы определить и реализоватьдругой контракт на обслуживание или использование ниже OperationContext и т. д.

OperationContext.Current.Channel.Faulted += delegate
{
    Console.WriteLine("");
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...