none
.Net Remoting: comment retrouner un objet du serveur vers un client (exemples) ? RRS feed

  • Question

  • Bonjour,

     

    Afin de valider une architecture pour une future application, je regarde en ce moment les possibilités offertes par .Net Remoting qui semble bien correspondre à mes besoins : nous maitrisons le coté serveur et le coté client et nous n'avons pas besoin d'ouvertures vers l'extérieur.

     

    J'ai réalisé quelques essais avec succès pour appler des méthodes qui retournent des valeurs simples (int, float, ...). Je souhaiterais maintenant aller plus loin et écrire des méthodes permettant d'échanger des objets entre le serveur et le client. Par exemple, comment retourner un objet initialisé par le serveur (lecture des infos en base de données par exemple) vers un client (et réciproquement) ? A première vue, il faut utiliser la sérialisation binaire, mais je n'arrive pas à trouver d'exemples complet sur le web. Si vous avez des pistes sur le sujet, je suis preneur ...

     

    Merci d'avance.

    François

    lundi 7 janvier 2008 09:07

Réponses

  • Bonjour,

    Voila tout d'abord un petit bout de code mettant en scène du remoting et le transfert d'un objet. Il y a 3 projets (le code est en VB.Net mais je peux le réécrire en C# si besoin) :

     

    TestLibrary : l'assembly partagée contenant l'interface de l'objet remoting et l'objet transféré :

     

    Extrait de code

    ' Fichier IUser.vb

    Public Interface IUser

    Function WhoAmI() As UserData

    End Interface

     

    ' Fichier UserData.vb

    Public Class UserData

    Private m_name As String

    Private m_birthdate As DateTime

     

    Public Sub New(ByVal name As String, ByVal birthdate As DateTime)

    Me.m_name = name

    Me.m_birthdate = birthdate

    End Sub

     

    Public Property Name() As String

    Get

    Return Me.m_name

    End Get

    Set(ByVal value As String)

    Me.m_name = value

    End Set

    End Property

     

    Public Property Birthdate() As DateTime

    Get

    Return Me.m_birthdate

    End Get

    Set(ByVal value As DateTime)

    Me.m_birthdate = value

    End Set

    End Property

     

    Public Overrides Function ToString() As String

    Return Me.m_name & " [" & Me.m_birthdate.ToShortDateString() & "]"

    End Function

    End Class

     

     

    TestServer : le serveur de remoting (hote et objet remoting) :

     

    Extrait de code

    ' Fichier User.cs

    Imports System.Threading

    Imports System.Security.Principal

    Imports TestLibrary

     

    Public Class User

    Inherits MarshalByRefObject

    Implements IUser

     

    Public Function WhoAmI() As UserData Implements TestLibrary.IUser.WhoAmI

    Return New UserData(Thread.CurrentPrincipal.Identity.Name, DateTime.Now)

    End Function

    End Class

     

    ' Fichier Module1.cs

    Imports System.Reflection

    Imports System.Runtime.Remoting

     

    Module Module1

    Sub Main()

    RemotingConfiguration.Configure(Assembly.GetEntryAssembly().Location & ".config", True)

     

    Console.WriteLine(System.Threading.Thread.CurrentPrincipal.Identity.Name)

    Console.WriteLine("Press ENTER to stop service...")

    Console.Read()

    End Sub

    End Module

     

     

    Le fichier de configuration du serveur :

     

    Extrait de code

    <?<!-- Fichier app.config -->

    <?xml version="1.0" encoding="utf-8" ?>

    <configuration>

    <system.runtime.remoting>

    <application>

    <service>

    <wellknown mode="Singleton" type="TestServer.User, TestServer" objectUri="User" />

    </service>

    <lifetime leaseTime="0" />

    <channels>

    <channel ref="tcp" port="9999" authenticationMode="IdentifyCallers">

    <serverProviders>

    <formatter ref="binary"/>

    </serverProviders>

    </channel>

    </channels>

    </application>

    </system.runtime.remoting>

    </configuration>

     

    TestClient : le client

     

    Extrait de code

    ' Fichier Module1.cs

    Imports System.Reflection

    Imports System.Runtime.Remoting

    Imports TestLibrary

     

    Module Module1

    Sub Main()

    RemotingConfiguration.Configure(Assembly.GetEntryAssembly().Location & ".config", True)

    Dim userService As IUser = TryCast(Activator.GetObject( _

    GetType(IUser) _

    , "tcp://localhost:9999/User" _

    ), IUser)

    Console.WriteLine(userService.WhoAmI().ToString())

    Console.Read()

    End Sub

    End Module

     

     

    Le fichier de configuration du client :

     

    Extrait de code

    <?<!-- Fichier app.config -->

    <?xml version="1.0" encoding="utf-8" ?>

    <configuration>

    <system.runtime.remoting>

    <application>

    <client>

    <wellknown type="TestLibrary.IUser, TestLibrary" url="tcp://10.128.249.234:9999/User"/>

    </client>

    <channels>

    <channel ref="tcp"/>

    </channels>

    </application>

    </system.runtime.remoting>

    </configuration>

     

     

    Pour déclarer une propriété dans une interface :

     

    Extrait de code

    VB.Net :

    Property ReadWriteProperty() As String

    ReadOnly Property ReadProperty() As String

    WriteOnly Property WriteProperty() As String

     

    C# :

    string ReadWriteProperty { get; set; }

    string ReadProperty { get}

    string WriteProperty { set; }

     

     

    Concernant la doc, la MSDN est a mon avis bien faite : http://207.46.199.254/en-us/library/72x4h507(VS.80).aspx

     

    Guillaume

    lundi 7 janvier 2008 10:48

Toutes les réponses

  • Bonjour,

    En remoting vous pouvez retouner n'importe quel objet à partir du moment ou celui-ci est sérialisable (attribut Serializable). Par contre vos deux applications, serveur et client, doivent partager une assembly contenant les classes qui seront transférées afin qu'elles connaissent la définition de ces classes. Cela est valable dans les 2 sens, client -> serveur et serveur -> client.

     

    Je vous conseil de faire un projet contenant l'ensemble des classes partagé par le client et le serveur ainsi que les interfaces exposées par vos objets remoting et de référencer ce projet (ou l'assembly générée) dans votre projet serveur et votre projet client.

     

    Guillaume

    lundi 7 janvier 2008 09:40
  • Merci pour ces informations, elles confirment ce que j'étais en train de découvrir. Je suis en train de faire un essai avec une classe bidon dont l'interface est commune entre client et serveur mais je découvre un peu les choses au fur et à mesure. Auriez-vous quelques liens sur des exemples concrêts ? Par exemple, comment déclarer une property (get/set) dans une interface ? Faut-il rendre l'interface sérialisable elle même ? etc ...

     

    Encore merci pour votre aide

    François.

     

    lundi 7 janvier 2008 09:58
  • Bonjour,

    Voila tout d'abord un petit bout de code mettant en scène du remoting et le transfert d'un objet. Il y a 3 projets (le code est en VB.Net mais je peux le réécrire en C# si besoin) :

     

    TestLibrary : l'assembly partagée contenant l'interface de l'objet remoting et l'objet transféré :

     

    Extrait de code

    ' Fichier IUser.vb

    Public Interface IUser

    Function WhoAmI() As UserData

    End Interface

     

    ' Fichier UserData.vb

    Public Class UserData

    Private m_name As String

    Private m_birthdate As DateTime

     

    Public Sub New(ByVal name As String, ByVal birthdate As DateTime)

    Me.m_name = name

    Me.m_birthdate = birthdate

    End Sub

     

    Public Property Name() As String

    Get

    Return Me.m_name

    End Get

    Set(ByVal value As String)

    Me.m_name = value

    End Set

    End Property

     

    Public Property Birthdate() As DateTime

    Get

    Return Me.m_birthdate

    End Get

    Set(ByVal value As DateTime)

    Me.m_birthdate = value

    End Set

    End Property

     

    Public Overrides Function ToString() As String

    Return Me.m_name & " [" & Me.m_birthdate.ToShortDateString() & "]"

    End Function

    End Class

     

     

    TestServer : le serveur de remoting (hote et objet remoting) :

     

    Extrait de code

    ' Fichier User.cs

    Imports System.Threading

    Imports System.Security.Principal

    Imports TestLibrary

     

    Public Class User

    Inherits MarshalByRefObject

    Implements IUser

     

    Public Function WhoAmI() As UserData Implements TestLibrary.IUser.WhoAmI

    Return New UserData(Thread.CurrentPrincipal.Identity.Name, DateTime.Now)

    End Function

    End Class

     

    ' Fichier Module1.cs

    Imports System.Reflection

    Imports System.Runtime.Remoting

     

    Module Module1

    Sub Main()

    RemotingConfiguration.Configure(Assembly.GetEntryAssembly().Location & ".config", True)

     

    Console.WriteLine(System.Threading.Thread.CurrentPrincipal.Identity.Name)

    Console.WriteLine("Press ENTER to stop service...")

    Console.Read()

    End Sub

    End Module

     

     

    Le fichier de configuration du serveur :

     

    Extrait de code

    <?<!-- Fichier app.config -->

    <?xml version="1.0" encoding="utf-8" ?>

    <configuration>

    <system.runtime.remoting>

    <application>

    <service>

    <wellknown mode="Singleton" type="TestServer.User, TestServer" objectUri="User" />

    </service>

    <lifetime leaseTime="0" />

    <channels>

    <channel ref="tcp" port="9999" authenticationMode="IdentifyCallers">

    <serverProviders>

    <formatter ref="binary"/>

    </serverProviders>

    </channel>

    </channels>

    </application>

    </system.runtime.remoting>

    </configuration>

     

    TestClient : le client

     

    Extrait de code

    ' Fichier Module1.cs

    Imports System.Reflection

    Imports System.Runtime.Remoting

    Imports TestLibrary

     

    Module Module1

    Sub Main()

    RemotingConfiguration.Configure(Assembly.GetEntryAssembly().Location & ".config", True)

    Dim userService As IUser = TryCast(Activator.GetObject( _

    GetType(IUser) _

    , "tcp://localhost:9999/User" _

    ), IUser)

    Console.WriteLine(userService.WhoAmI().ToString())

    Console.Read()

    End Sub

    End Module

     

     

    Le fichier de configuration du client :

     

    Extrait de code

    <?<!-- Fichier app.config -->

    <?xml version="1.0" encoding="utf-8" ?>

    <configuration>

    <system.runtime.remoting>

    <application>

    <client>

    <wellknown type="TestLibrary.IUser, TestLibrary" url="tcp://10.128.249.234:9999/User"/>

    </client>

    <channels>

    <channel ref="tcp"/>

    </channels>

    </application>

    </system.runtime.remoting>

    </configuration>

     

     

    Pour déclarer une propriété dans une interface :

     

    Extrait de code

    VB.Net :

    Property ReadWriteProperty() As String

    ReadOnly Property ReadProperty() As String

    WriteOnly Property WriteProperty() As String

     

    C# :

    string ReadWriteProperty { get; set; }

    string ReadProperty { get}

    string WriteProperty { set; }

     

     

    Concernant la doc, la MSDN est a mon avis bien faite : http://207.46.199.254/en-us/library/72x4h507(VS.80).aspx

     

    Guillaume

    lundi 7 janvier 2008 10:48
  • Merci pour tout. J'ai réalisé un programme de test et tout fonctionne super bien; je suis d'autant plus content qu'en dessous de mon serveur il y a de l'intéropérabilité avec du code C++/MFC et que tout le monde se cause !

     

    François.

     

    lundi 7 janvier 2008 13:33