mardi 12 août 2014

Canaux nommés (Named Pipe).

Le canal nommé (Named Pipe) permet de créer un canal de communication entre deux applications. La première application, de type "serveur", va crée le "Pipe". Ceci va permettre à un ou plusieurs clients de se connecter à l'application serveur. La seconde application va récupérer les informations de la première application via le Pipe.

Dans l'exemple suivant, je vais exploiter l'un des avantages du canal nommé en mode duplex. La propriété duplex permet au client et au serveur d'envoyer et de recevoir des informations, permettant ainsi aux deux applications de dialoguer entre elles.

Application serveur.


Le premier script fera office de serveur et il tournera dans son propre environnement PowerShell. Son rôle sera de créer le canal nommé, d'attendre les informations du client et de retourner une réponse. Bien entendu, ce script devra être exécuté en premier.


 
[Reflection.Assembly]::LoadWithPartialName("system.core")

#Ouverture du pipe en mode duplex.
Write-Host "Démarrage du serveur."
$pipeDir = [System.IO.Pipes.PipeDirection]::InOut
$pipe = new-object System.IO.Pipes.NamedPipeServerStream("\\.\pipe\jumbor12",$pipeDir)
$pipe.WaitForConnection()

#Déclaration des objets pour la lecture/écriture dans le pipe.
$sr = new-object System.IO.StreamReader($pipe)
$sw = new-object System.IO.StreamWriter($pipe)
$sw.AutoFlush = $true

#Ecoute du client.
while (($line = $sr.ReadLine()) -ne "Exit")
 {
   #Réponses.
   Write-Host $line
   if ($line -eq "Hello !") { $sw.WriteLine("Bonjour !") }
   if ($line -eq "Bye !")   { $sw.WriteLine("Bonsoir !") }
 }

#Dispose.
Write-Host "Arrêt du serveur."
$sw.Dispose()
$pipe.Dispose()

#Fin.


Application client.


Le second script sera le client. Il va se connecter au canal nommé du serveur et l'interroger. Il attendre la réponse du serveur, et l'affichera dans la console. Ce script doit être lancé depuis un nouvel environnement PowerShell. Et bien entendu devra être exécuté en même temps que le premier script. Sinon ça ne marchera pas ^^.


 
[Reflection.Assembly]::LoadWithPartialName("system.core")

#Connexion au pipe du serveur.
Write-host "Démarrage du client."
$timeout = 5000 #5 secondes
$pipe = new-object System.IO.Pipes.NamedPipeClientStream("\\.\pipe\jumbor12")
$pipe.Connect($timeout)
if (!$pipe.IsConnected)
  {
    Write-Host "Merci de vérifier si le serveur est lancé."
    Return
  }
 
#Déclaration des objets pour la lecture/écriture dans le pipe.
$sr = new-object System.IO.StreamReader($pipe)
$sw = new-object System.IO.StreamWriter($pipe)
$sw.AutoFlush = $true

#Interroger le serveur.
$sw.WriteLine("Hello !")

#Attendre la réponse.
Write-Host $sr.ReadLine()

#Interroger le serveur.
$sw.WriteLine("Bye !")

#Attendre la réponse.
Write-Host $sr.ReadLine()

#Arrêter le serveur.
$sw.WriteLine("Exit")

#Dispose.
Write-Host "Arrêt du client."
$sw.Dispose()
$pipe.Dispose()

#Fin.