Минимальный пример именованного канала WCF

90

Я ищу минимальный пример именованных каналов WCF (я ожидаю два минимальных приложения, сервер и клиент, которые могут взаимодействовать через именованный канал).

У Microsoft есть блестящая статья « Учебник по началу работы», в которой описывается WCF через HTTP, и я ищу что-то похожее на WCF и именованные каналы.

Я нашел несколько постов в Интернете, но они несколько «продвинутые». Мне нужно что-то минимальное, только обязательная функциональность, чтобы я мог добавить свой код и заставить приложение работать.

Как мне заменить это, чтобы использовать именованный канал?

<endpoint address="http://localhost:8000/ServiceModelSamples/Service/CalculatorService"
    binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICalculator"
    contract="ICalculator" name="WSHttpBinding_ICalculator">
    <identity>
        <userPrincipalName value="OlegPc\Oleg" />
    </identity>
</endpoint>

Как мне заменить это, чтобы использовать именованный канал?

// Step 1 of the address configuration procedure: Create a URI to serve as the base address.
Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service");

// Step 2 of the hosting procedure: Create ServiceHost
ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress);

try
{
    // Step 3 of the hosting procedure: Add a service endpoint.
    selfHost.AddServiceEndpoint(
        typeof(ICalculator),
        new WSHttpBinding(),
        "CalculatorService");

    // Step 4 of the hosting procedure: Enable metadata exchange.
    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
    smb.HttpGetEnabled = true;
    selfHost.Description.Behaviors.Add(smb);

    // Step 5 of the hosting procedure: Start (and then stop) the service.
    selfHost.Open();
    Console.WriteLine("The service is ready.");
    Console.WriteLine("Press <ENTER> to terminate service.");
    Console.WriteLine();
    Console.ReadLine();

    // Close the ServiceHostBase to shutdown the service.
    selfHost.Close();
}
catch (CommunicationException ce)
{
    Console.WriteLine("An exception occurred: {0}", ce.Message);
    selfHost.Abort();
}

Как создать клиента для использования именованного канала?

Олег Важнев
источник
1
вы смотрели stackoverflow.com/questions/184878/… ?
Кристоф

Ответы:

80

Я только что нашел этот отличный небольшой учебник . неработающая ссылка ( кешированная версия )

Я также следил за учебником Microsoft, что приятно, но мне также нужны были только трубы.

Как видите, вам не нужны файлы конфигурации и все такое.

Кстати, он использует и HTTP, и трубы. Просто удалите все строки кода, относящиеся к HTTP, и вы получите чистый пример канала.

Хуан
источник
2
Благодарность! Кроме того, при попытке создать службу, которая использует web.config для своей конфигурации вместо жестко заданной конфигурации, см. Этот пример microsoft: msdn.microsoft.com/en-us/library/ms752253.aspx
Nullius
3
Ссылка не работает, учебник где-нибудь еще?
user1069816
Просто потратил некоторое время, пытаясь понять, почему «трубка закончилась». Вот мое решение по этому поводу, надеюсь, поможет: stackoverflow.com/a/49075797/385273
Бен
62

Попробуй это.

Вот и служебная часть.

[ServiceContract]
public interface IService
{
    [OperationContract]
    void  HelloWorld();
}

public class Service : IService
{
    public void HelloWorld()
    {
        //Hello World
    }
}

Вот прокси

public class ServiceProxy : ClientBase<IService>
{
    public ServiceProxy()
        : base(new ServiceEndpoint(ContractDescription.GetContract(typeof(IService)),
            new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/MyAppNameThatNobodyElseWillUse/helloservice")))
    {

    }
    public void InvokeHelloWorld()
    {
        Channel.HelloWorld();
    }
}

И вот часть услуги хостинга.

var serviceHost = new ServiceHost
        (typeof(Service), new Uri[] { new Uri("net.pipe://localhost/MyAppNameThatNobodyElseWillUse") });
    serviceHost.AddServiceEndpoint(typeof(IService), new NetNamedPipeBinding(), "helloservice");
    serviceHost.Open();

    Console.WriteLine("Service started. Available in following endpoints");
    foreach (var serviceEndpoint in serviceHost.Description.Endpoints)
    {
        Console.WriteLine(serviceEndpoint.ListenUri.AbsoluteUri);
    }
Анурадж
источник
Это может работать, но это не так гибко, как простое редактирование файлов app.config для клиента и сервера ...
Алан С.
9
Приятно, поскольку раскрытие деталей приложения через файлы app.config часто нежелательно.
Фрэнк Хайлман
14
Это замечательный пример, однако никогда не используйте базовый адрес только net.pipe: // localhost /. Если вы это сделаете, и на машине есть какая-либо другая программа, которая также использует net.pipe: // localhost /, тогда ServiceHost выдаст исключение, когда вы его откроете. Вместо этого используйте что-нибудь уникальное, например net.pipe: // localhost / MyAppNameThatNobodyElseWillUse. Надеюсь, это поможет кому-то еще сэкономить время и нервы!
Дуг Клаттер
Это решение работает хорошо. В частности, для внутренних конечных точек, где ссылка на службу в конфигурации не требуется. Просто сохраните контракты - просто определения интерфейсов - в их собственной сборке и, возможно, адрес в config. Маловероятно, что привязка изменится.
Роб фон Нессельроде,
2
Мне нужно было добавить /helloserviceв конец адреса конечной точки в прокси.
Mormegil
14

Посмотрите мой очень упрощенный пример Echo : он разработан для использования базовой HTTP-связи, но его можно легко изменить для использования именованных каналов, отредактировав файлы app.config для клиента и сервера. Сделайте следующие изменения:

Отредактируйте файл app.config сервера , удалив или закомментировав запись http baseAddress и добавив новую запись baseAddress для именованного канала (называемого net.pipe ). Кроме того, если вы не собираетесь использовать HTTP в качестве протокола связи, убедитесь, что serviceMetadata и serviceDebug закомментированы или удалены:

<configuration>
    <system.serviceModel>
        <services>
            <service name="com.aschneider.examples.wcf.services.EchoService">
                <host>
                    <baseAddresses>
                        <add baseAddress="net.pipe://localhost/EchoService"/>
                    </baseAddresses>
                </host>
            </service>
        </services>
        <behaviors>
            <serviceBehaviors></serviceBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>

Отредактируйте клиентский файл app.config, чтобы привязка basicHttpBinding была либо закомментирована, либо удалена и добавлена запись netNamedPipeBinding . Вам также потребуется изменить запись конечной точки, чтобы использовать канал:

<configuration>
    <system.serviceModel>
        <bindings>
            <netNamedPipeBinding>
                <binding name="NetNamedPipeBinding_IEchoService"/>
            </netNamedPipeBinding>
        </bindings>
        <client>
            <endpoint address              = "net.pipe://localhost/EchoService"
                      binding              = "netNamedPipeBinding"
                      bindingConfiguration = "NetNamedPipeBinding_IEchoService"
                      contract             = "EchoServiceReference.IEchoService"
                      name                 = "NetNamedPipeBinding_IEchoService"/>
        </client>
    </system.serviceModel>
</configuration>

Приведенный выше пример будет работать только с именованными каналами, но ничто не мешает вам использовать несколько протоколов для запуска вашей службы. AFAIK, у вас должна быть возможность запустить службу на сервере, используя как именованные каналы, так и HTTP (а также другие протоколы).

Кроме того, значительно упрощена привязка в клиентском файле app.config . Есть множество различных параметров, которые вы можете настроить, помимо простого указания baseAddress ...

Алан С
источник
5
Ссылки теперь мертвы.
Крис Вебер,
2

Я создал этот простой пример из различных результатов поиска в Интернете.

public static ServiceHost CreateServiceHost(Type serviceInterface, Type implementation)
{
  //Create base address
  string baseAddress = "net.pipe://localhost/MyService";

  ServiceHost serviceHost = new ServiceHost(implementation, new Uri(baseAddress));

  //Net named pipe
  NetNamedPipeBinding binding = new NetNamedPipeBinding { MaxReceivedMessageSize = 2147483647 };
  serviceHost.AddServiceEndpoint(serviceInterface, binding, baseAddress);

  //MEX - Meta data exchange
  ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
  serviceHost.Description.Behaviors.Add(behavior);
  serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexNamedPipeBinding(), baseAddress + "/mex/");

  return serviceHost;
}

Используя указанный выше URI, я могу добавить в свой клиент ссылку на веб-службу.

Рахбек
источник
-2

Я нашел этот сайт действительно полезным, и пример проекта работает без каких-либо настроек: https://dotnet-experience.blogspot.com/2012/02/inter-process-duplex-communication-with.html

Не забудьте включить поддержку именованных каналов в компонентах Windows. В этой статье есть несколько хороших снимков экрана на этот счет в верхнем ответе: Именованный канал WCF в службе Windows с использованием App.Config

Проект, указанный в принятом решении, не работает на моем ПК без изменений. Я попробовал исправить несколько ошибок в app.config, но все равно получил следующее исключение:

System.InvalidOperationException: «Служба» WpfWcfNamedPipeBinding.NamedPipeBindingService »не имеет конечных точек приложения (не связанных с инфраструктурой). Это может быть связано с тем, что для вашего приложения не найден файл конфигурации, или потому, что в файле конфигурации не может быть найден элемент службы, соответствующий имени службы, или потому, что в элементе службы не определены конечные точки.

ГолосоватьКофе
источник