WCF Named Pipe Minimal Beispiel


90

Ich suche nach einem minimalen Beispiel für WCF Named Pipes (ich erwarte zwei minimale Anwendungen, Server und Client, die über eine Named Pipe kommunizieren können.)

Microsoft hat den brillanten Artikel Erste Schritte Tutorial , der WCF über HTTP beschreibt, und ich suche nach etwas Ähnlichem über WCF und Named Pipes.

Ich habe mehrere Beiträge im Internet gefunden, aber sie sind etwas "fortgeschritten". Ich benötige nur minimale, nur obligatorische Funktionen, damit ich meinen Code hinzufügen und die Anwendung zum Laufen bringen kann.

Wie ersetze ich das, um eine Named Pipe zu verwenden?

<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>

Wie ersetze ich das, um eine Named Pipe zu verwenden?

// 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();
}

Wie generiere ich einen Client für die Verwendung einer Named Pipe?


Antworten:


80

Ich habe gerade dieses ausgezeichnete kleine Tutorial gefunden . defekter Link (zwischengespeicherte Version )

Ich habe auch das Tutorial von Microsoft befolgt, was nett ist, aber ich brauchte auch nur Pipes.

Wie Sie sehen können, benötigen Sie keine Konfigurationsdateien und all das unordentliche Zeug.

Übrigens verwendet er sowohl HTTP als auch Pipes. Entfernen Sie einfach alle Codezeilen, die sich auf HTTP beziehen, und Sie erhalten ein reines Pipe-Beispiel.


2
Vielen Dank! Wenn Sie versuchen, einen Dienst zu erstellen, der die web.config für die Konfiguration anstelle der fest codierten Konfiguration verwendet, lesen Sie dieses Microsoft-Beispiel: msdn.microsoft.com/en-us/library/ms752253.aspx
Nullius

3
Der Link funktioniert nicht, ist das Tutorial irgendwo anders?
user1069816

Ich habe gerade eine Weile versucht herauszufinden, warum die "Pipe beendet wurde". Hier ist meine Lösung für dieses Problem
Ben

62

Versuche dies.

Hier ist der Serviceteil.

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

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

Hier ist der Proxy

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();
    }
}

Und hier ist der Service-Hosting-Teil.

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);
    }

Dies mag funktionieren, ist aber nicht so flexibel wie das Bearbeiten der app.config-Dateien für Client und Server ...
Alan S

9
Schön, da das Offenlegen der Anwendungsdetails über app.config-Dateien oft nicht erwünscht ist.
Frank Hileman

14
Dies ist ein wunderbares Beispiel. Verwenden Sie jedoch niemals eine Basisadresse von nur net.pipe: // localhost /. Wenn Sie dies tun und der Computer über ein anderes Programm verfügt, das ebenfalls net.pipe: // localhost / verwendet, löst ServiceHost beim Öffnen eine Ausnahme aus. Verwenden Sie stattdessen etwas Einzigartiges wie net.pipe: // localhost / MyAppNameThatNobodyElseWillUse. Hoffe, das hilft jemand anderem Zeit und Frust zu sparen!
Doug Clutter

Diese Lösung funktioniert gut. Insbesondere für interne Endpunkte, bei denen eine Dienstreferenz in der Konfiguration nicht erforderlich ist. Behalten Sie einfach die Verträge - einfach die Schnittstellendefinitionen - in ihrer eigenen Assembly und möglicherweise die Adresse in config. Es ist nicht so wahrscheinlich, dass sich die Bindung ändert.
Rob Von Nesselrode

2
Ich musste /helloserviceam Ende der Endpunktadresse im Proxy hinzufügen .
Mormegil

14

Schauen Sie sich mein stark vereinfachtes Echo-Beispiel an : Es wurde für die Verwendung der grundlegenden HTTP-Kommunikation entwickelt, kann jedoch leicht geändert werden, um Named Pipes zu verwenden, indem die Dateien app.config für Client und Server bearbeitet werden. Nehmen Sie folgende Änderungen vor:

Bearbeiten Sie die Datei app.config des Servers , entfernen oder kommentieren Sie den Eintrag http baseAddress und fügen Sie einen neuen baseAddress- Eintrag für die Named Pipe hinzu ( net.pipe genannt ). Auch wenn Sie nicht beabsichtigen , HTTP zur Verwendung für ein Kommunikationsprotokoll, stellen Sie sicher , dass die serviceMetadata und serviceDebug entweder kommentiert oder gestrichen:

<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>

Bearbeiten Sie die Datei app.config des Clients so, dass die basicHttpBinding entweder auskommentiert oder gelöscht wird und ein netNamedPipeBinding- Eintrag hinzugefügt wird. Sie müssen auch den Endpunkteintrag ändern , um die Pipe zu verwenden:

<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>

Das obige Beispiel wird nur mit Named Pipes ausgeführt, aber nichts hindert Sie daran, mehrere Protokolle zum Ausführen Ihres Dienstes zu verwenden. AFAIK, Sie sollten in der Lage sein, einen Server einen Dienst ausführen zu lassen, der sowohl Named Pipes als auch HTTP (sowie andere Protokolle) verwendet.

Außerdem wird die Bindung in der app.config- Datei des Clients stark vereinfacht. Es gibt viele verschiedene Parameter, die Sie anpassen können, abgesehen von der Angabe der baseAddress ...


5
Die Links sind jetzt tot.
Chris Weber

2

Ich habe dieses einfache Beispiel aus verschiedenen Suchergebnissen im Internet erstellt.

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;
}

Mit der obigen URI kann ich dem Webdienst eine Referenz in meinem Client hinzufügen.


-2

Ich fand diese Seite wirklich hilfreich und das Beispielprojekt läuft ohne Änderungen: https://dotnet-experience.blogspot.com/2012/02/inter-process-duplex-communication-with.html

Vergessen Sie nicht, die Named Pipe-Unterstützung in den Windows-Funktionen zu aktivieren. Dieser Artikel enthält einige gute Screenshots zu diesem Zweck in der oberen Antwort: WCF Named Pipe im Windows-Dienst mit App.Config

Das Projekt, auf das in der akzeptierten Lösung verwiesen wird, läuft auf meinem PC nicht wie es ist. Ich habe einige Korrekturen in der app.config versucht, erhalte aber immer noch die folgende Ausnahme:

System.InvalidOperationException: 'Service' WpfWcfNamedPipeBinding.NamedPipeBindingService 'hat keine Anwendungsendpunkte (ohne Infrastruktur). Dies kann daran liegen, dass für Ihre Anwendung keine Konfigurationsdatei gefunden wurde oder dass in der Konfigurationsdatei kein mit dem Dienstnamen übereinstimmendes Dienstelement gefunden wurde oder dass im Dienstelement keine Endpunkte definiert wurden. '

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.