WCF назвав мінімальний приклад труби


90

Я шукаю мінімальний приклад WCF Named Pipes (я очікую два мінімальні додатки, сервер і клієнт, які можуть спілкуватися через іменовану трубу.)

Корпорація Майкрософт має чудову статтю Початок роботи, яка описує 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 для клієнта та сервера ...
Alan S

9
Приємно, оскільки виставляти деталі програми за допомогою файлів app.config часто не бажано.
Frank Hileman

14
Це прекрасний приклад, однак, ніколи не використовуйте базову адресу просто net.pipe: // localhost /. Якщо ви це зробите, і машина має будь-яку іншу програму, яка також використовує net.pipe: // localhost /, тоді ServiceHost видасть виняток, коли ви його відкриєте. Натомість використовуйте щось унікальне, наприклад net.pipe: // localhost / MyAppNameThatNobodyElseWillUse. Сподіваюся, це допоможе економити комусь ще трохи часу та розчарувань!
Даг Кламтер

Це рішення добре працює. Зокрема, для внутрішніх кінцевих точок, де посилання на службу в конфігурації не потрібно. Просто зберігайте контракти - просто визначення інтерфейсу - у власній збірці та, можливо, адресу в конфігурі. Не настільки ймовірно, що прив'язка зміниться.
Роб Фон Нессельроде

2
Мені потрібно було додати /helloserviceдо кінця адресу кінцевої точки в проксі.
Мормегіл

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

Не забудьте увімкнути підтримку Named Pipe у функціях Windows. У цій статті є кілька хороших знімків екрану для цього у верхній відповіді: WCF Named Pipe в службі Windows за допомогою App.

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

System.InvalidOperationException: 'Служба' WpfWcfNamedPipeBinding.NamedPipeBindingService 'має нульові кінцеві точки застосування (не інфраструктури). Це може бути тому, що для вашої програми не знайдено файлу конфігурації, або тому, що у файлі конфігурації не знайдено елемента служби, що відповідає імені служби, або тому, що в елементі служби не визначено кінцевих точок. '

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.