Esempio minimo di pipa denominata WCF


90

Sto cercando un esempio minimo di WCF Named Pipe (mi aspetto due applicazioni minime, server e client, che possono comunicare tramite una named pipe.)

Microsoft ha il brillante articolo Tutorial introduttivo che descrive WCF tramite HTTP e sto cercando qualcosa di simile su WCF e named pipe.

Ho trovato diversi post in Internet, ma sono un po '"avanzati". Ho bisogno di qualcosa di minimo, solo di funzionalità obbligatorie, così posso aggiungere il mio codice e far funzionare l'applicazione.

Come lo sostituisco per usare una named pipe?

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

Come lo sostituisco per usare una named pipe?

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

Come faccio a generare un client per utilizzare una named pipe?


Risposte:


80

Ho appena trovato questo eccellente piccolo tutorial . collegamento interrotto ( versione cache )

Ho anche seguito il tutorial di Microsoft che è carino, ma mi servivano solo pipe.

Come puoi vedere, non hai bisogno di file di configurazione e tutte quelle cose disordinate.

A proposito, usa sia HTTP che pipe. Basta rimuovere tutte le righe di codice relative a HTTP e otterrai un esempio di pipe puro.


2
Grazie! Inoltre, quando si tenta di creare un servizio che utilizza web.config per la sua configurazione invece della configurazione hardcoded, vedere questo esempio microsoft: msdn.microsoft.com/en-us/library/ms752253.aspx
Nullius

3
Il collegamento non funziona, il tutorial è da qualche altra parte?
user1069816

Ho appena passato un po 'a cercare di capire perché "il tubo è stato chiuso". Ecco la mia soluzione su questo, si spera che aiuti: stackoverflow.com/a/49075797/385273
Ben

62

Prova questo.

Ecco la parte di servizio.

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

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

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

Ed ecco la parte di hosting del servizio.

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

Potrebbe funzionare, ma non è così flessibile come la semplice modifica dei file app.config per client e server ...
Alan S

9
Bello, dal momento che l'esposizione dei dettagli dell'applicazione tramite i file app.config spesso non è desiderata.
Frank Hileman

14
Questo è un meraviglioso esempio, tuttavia, non utilizzare mai un indirizzo di base solo net.pipe: // localhost /. Se lo fai e la macchina ha un altro programma che utilizza anche net.pipe: // localhost /, ServiceHost genererà un'eccezione quando lo apri. Invece, usa qualcosa di unico come net.pipe: // localhost / MyAppNameThatNobodyElseWillUse. Spero che questo aiuti a risparmiare tempo e frustrazione a qualcun altro!
Doug Clutter,

Questa soluzione funziona bene. In particolare per gli endpoint interni in cui non è necessario avere un riferimento al servizio nella configurazione. Mantieni semplicemente i contratti - semplicemente le definizioni dell'interfaccia - nel loro assembly e forse l'indirizzo in config. Non è così probabile che l'associazione cambierà.
Rob Von Nesselrode

2
Avevo bisogno di aggiungere /helloservicealla fine dell'indirizzo dell'endpoint nel proxy.
Mormegil

14

Guarda il mio esempio Echo altamente semplificato : è progettato per utilizzare la comunicazione HTTP di base, ma può essere facilmente modificato per utilizzare pipe denominate modificando i file app.config per il client e il server. Apporta le seguenti modifiche:

Modifica il file app.config del server , rimuovendo o aggiungendo un commento alla voce http baseAddress e aggiungendo una nuova voce baseAddress per la named pipe (chiamata net.pipe ). Inoltre, se non intendi utilizzare HTTP per un protocollo di comunicazione, assicurati che serviceMetadata e serviceDebug siano commentati o eliminati:

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

Modificare il file app.config del client in modo che basicHttpBinding venga commentato o eliminato e venga aggiunta una voce netNamedPipeBinding . Sarà inoltre necessario modificare la voce dell'endpoint per utilizzare la pipe:

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

L'esempio precedente verrà eseguito solo con named pipe, ma nulla ti impedisce di utilizzare più protocolli per eseguire il tuo servizio. AFAIK, dovresti essere in grado di fare in modo che un server esegua un servizio utilizzando sia named pipe che HTTP (così come altri protocolli).

Inoltre, l'associazione nel file app.config del client è molto semplificata. Ci sono molti parametri diversi che puoi regolare, oltre a specificare semplicemente baseAddress ...


5
I collegamenti ora sono morti.
Chris Weber

2

Ho creato questo semplice esempio da diversi risultati di ricerca su Internet.

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

Usando l'URI sopra posso aggiungere un riferimento nel mio client al servizio web.


-2

Ho trovato questo sito davvero utile e il progetto di esempio viene eseguito senza alcun ritocco: https://dotnet-experience.blogspot.com/2012/02/inter-process-duplex-communication-with.html

Non dimenticare di abilitare il supporto per pipe con nome nelle funzionalità di Windows. Questo articolo ha alcuni buoni screenshot in tal senso nella risposta principale: WCF Named Pipe nel servizio Windows utilizzando App.Config

Il progetto a cui si fa riferimento nella soluzione accettata non viene eseguito così com'è sul mio PC. Ho provato alcune correzioni in app.config ma ricevo ancora la seguente eccezione:

System.InvalidOperationException: "Service" WpfWcfNamedPipeBinding.NamedPipeBindingService "ha zero endpoint dell'applicazione (non infrastrutturali). Ciò potrebbe essere dovuto al fatto che non è stato trovato alcun file di configurazione per la tua applicazione, o perché nel file di configurazione non è stato trovato alcun elemento del servizio corrispondente al nome del servizio o perché non sono stati definiti endpoint nell'elemento del servizio. "

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.