Exemple de canal minimal nommé WCF

90

Je recherche un exemple minimal de tuyaux nommés WCF (j'attends deux applications minimales, serveur et client, qui peuvent communiquer via un tuyau nommé.)

Microsoft a le brillant article Getting Started Tutorial qui décrit WCF via HTTP, et je recherche quelque chose de similaire à propos de WCF et des canaux nommés.

J'ai trouvé plusieurs articles sur Internet, mais ils sont un peu "avancés". J'ai besoin de quelque chose de minimal, uniquement des fonctionnalités obligatoires, afin que je puisse ajouter mon code et faire fonctionner l'application.

Comment remplacer cela pour utiliser un tube nommé?

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

Comment remplacer cela pour utiliser un tube nommé?

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

Comment générer un client pour utiliser un canal nommé?

javapowered
la source
1
avez-vous regardé stackoverflow.com/questions/184878/... ?
Christoph

Réponses:

80

Je viens de trouver cet excellent petit tutoriel . lien cassé ( version mise en cache )

J'ai également suivi le tutoriel de Microsoft, ce qui est bien, mais je n'avais également besoin que de tuyaux.

Comme vous pouvez le voir, vous n'avez pas besoin de fichiers de configuration et de tout ce qui est compliqué.

À propos, il utilise à la fois HTTP et des tubes. Supprimez simplement toutes les lignes de code liées à HTTP et vous obtiendrez un exemple purement de pipe.

Juan
la source
2
Merci! En outre, lorsque vous essayez de créer un service qui utilise le web.config pour sa configuration au lieu de la configuration codée en dur, consultez cet exemple Microsoft: msdn.microsoft.com/en-us/library/ms752253.aspx
Nullius
3
Le lien ne fonctionne pas, le tutoriel est-il ailleurs?
user1069816
Je viens de passer un moment à essayer de comprendre pourquoi le "tuyau a été terminé". Voici ma solution à ce sujet, j'espère que cela aidera: stackoverflow.com/a/49075797/385273
Ben
62

Essaye ça.

Voici la partie service.

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

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

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

Et voici la partie hébergement du service.

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);
    }
Anuraj
la source
Cela peut fonctionner, mais ce n'est pas aussi flexible que de simplement modifier les fichiers app.config pour le client et le serveur ...
Alan S
9
Bien, car exposer les détails de l'application via des fichiers app.config n'est souvent pas souhaité.
Frank Hileman
14
Ceci est un exemple merveilleux, cependant, n'utilisez jamais une adresse de base de net.pipe: // localhost /. Si vous le faites et que la machine a un autre programme qui utilise également net.pipe: // localhost /, ServiceHost lèvera une exception lorsque vous l'ouvrirez. Au lieu de cela, utilisez quelque chose d'unique comme net.pipe: // localhost / MyAppNameThatNobodyElseWillUse. J'espère que cela aidera quelqu'un d'autre à gagner du temps et de la frustration!
Doug Clutter
Cette solution fonctionne bien. En particulier pour les points de terminaison internes où il n'est pas nécessaire d'avoir une référence de service dans la configuration. Gardez simplement les contrats - simplement les définitions d'interface - dans leur propre assemblage et peut-être l'adresse dans config. Il est peu probable que la liaison change.
Rob Von Nesselrode
2
J'avais besoin d'ajouter /helloserviceà la fin de l'adresse du point de terminaison dans le proxy.
Mormegil
14

Consultez mon exemple Echo hautement simplifié : il est conçu pour utiliser la communication HTTP de base, mais il peut facilement être modifié pour utiliser des tubes nommés en éditant le app.config fichiers pour le client et le serveur. Apportez les modifications suivantes:

Modifiez le fichier app.config du serveur , supprimez ou commentez l' entrée http baseAddress et ajoutez une nouvelle entrée baseAddress pour le tube nommé (appelé net.pipe ). En outre, si vous ne prévoyez pas d'utiliser HTTP pour un protocole de communication, assurez - vous que le serviceMetadata et serviceDebug est soit en commentaires ou supprimés:

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

Modifiez le fichier app.config du client afin que basicHttpBinding soit mis en commentaire ou supprimé et qu'une entrée netNamedPipeBinding soit ajoutée. Vous devrez également modifier l' entrée du point de terminaison pour utiliser le canal:

<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'exemple ci-dessus ne fonctionnera qu'avec des canaux nommés, mais rien ne vous empêche d'utiliser plusieurs protocoles pour exécuter votre service. AFAIK, vous devriez pouvoir faire exécuter un service par un serveur en utilisant à la fois des canaux nommés et HTTP (ainsi que d'autres protocoles).

En outre, la liaison dans le fichier app.config du client est très simplifiée. Il existe de nombreux paramètres que vous pouvez régler, en plus de spécifier simplement la baseAddress ...

Alan S
la source
5
Les liens sont maintenant morts.
Chris Weber
2

J'ai créé cet exemple simple à partir de différents résultats de recherche sur 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;
}

En utilisant l'URI ci-dessus, je peux ajouter une référence dans mon client au service Web.

Rahbek
la source
-2

J'ai trouvé ce site vraiment utile et l'exemple de projet s'exécute sans aucune modification: https://dotnet-experience.blogspot.com/2012/02/inter-process-duplex-communication-with.html

N'oubliez pas d'activer la prise en charge du canal nommé dans les fonctionnalités Windows. Cet article a quelques bonnes captures d'écran à cet effet dans la réponse du haut: Canal nommé WCF dans le service Windows à l'aide d'App.Config

Le projet référencé dans la solution acceptée ne s'exécute pas tel quel sur mon PC. J'ai essayé quelques correctifs dans app.config mais j'obtiens toujours l'exception suivante:

System.InvalidOperationException: 'Service' WpfWcfNamedPipeBinding.NamedPipeBindingService 'n'a aucun point de terminaison d'application (non-infrastructure). Cela peut être dû au fait qu’aucun fichier de configuration n’a été trouvé pour votre application, qu’aucun élément de service correspondant au nom du service n’a pu être trouvé dans le fichier de configuration, ou qu’aucun point de terminaison n’a été défini dans l’élément de service. »

VoteCafé
la source