Quick Search for:  in language:    
article,meant,step,guide,give,reader,gist,Rem
   Code/Articles » |  Newest/Best » |  Community » |  Jobs » |  Other » |  Goto » | 
CategoriesSearch Newest CodeCoding ContestCode of the DayAsk A ProJobsUpload
.Net Stats

 Code: 140,189. lines
 Jobs: 376. postings

 How to support the site

 
Sponsored by:

 
You are in:
 

Does your code think in ink?
Login





Latest Code Ticker for .Net.
Click here to see a screenshot of this code!Ray Picking for 3d Objects
By Jay1_z on 11/23

(Screen Shot)

Embed Images into Xml Files
By Chris Richards on 11/23


Encryption and Alternate Data Stream
By Philip Pierce on 11/23


Click here to see a screenshot of this code!AddressBook
By Ekong George Ekong on 11/23

(Screen Shot)

Click here to see a screenshot of this code!Command Line Redirection
By kaze on 11/23

(Screen Shot)

Fader
By Ahmad Hammad on 11/23


Click here to see a screenshot of this code!Get content of a web page (simple)
By Tin Trung Dang on 11/22

(Screen Shot)

Retrieve the long path name for a short path name.
By Özgür Aytekin on 11/22


Easy Randomizer
By Christian Müller on 11/22


Click here to put this ticker on your site!


Add this ticker to your desktop!


Daily Code Email
To join the 'Code of the Day' Mailing List click here!

Affiliate Sites



 
 
   

Net Remoting in Simple English (Really, it's that simple)

Print
Email
 

Submitted on: 6/13/2003 7:37:24 AM
By: Daniel Ang C. M.  
Level: Beginner
User Rating: By 13 Users
Compatibility:VB.NET

Users have accessed this article 5263 times.
 

(About the author)
 
     This article is meant to be a step by step guide to give its reader a gist of .Net Remoting. I've tried to search good tutorials, but it was rather hard to find one that could work on my PC! So here's my first shot at a .Net Remoting tutorial in VB.net. It shouldn't be hard to get it running, if you'd follow this few steps.

This article has accompanying files

 
 
Terms of Agreement:   
By using this article, you agree to the following terms...   
1) You may use this article in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.   
2) You MAY NOT redistribute this article (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
3) You may link to this article from another website, but ONLY if it is not wrapped in a frame. 
4) You will abide by any additional copyright restrictions which the author may have placed in the article or article's description.

Introduction

This article is meant to be a step by step guide to give its reader a gist of .Net Remoting. I've tried to search good tutorials, but it was rather hard to find one that could work on my PC! So here's my first shot at a .Net Remoting tutorial in VB.net. It shouldn't be hard to get it running, if you'd follow this few steps.

Background

It's important for you to understand what's going on before we dive into the code (don't worry, it's not really hard). First off, we will have a remotable object called Manager, which will be a singleton object (defined later). Clients will send their messages by calling a method in the one and only one (singleton) Manager object called SendText, which in turn will raise an event, evtReceiveText. This event will be handled by all the chat clients, which then will display the received message on the textbox, txtReceivedMsgs.

OK, let's conceptualize it, we have one and only one remotable object, called the Manager, from the namespace InBetween (which conceptually, sits in between the server and client, serializing messages to and fro). Next, we have one Server, which will register or create a new instance our own well known service or application, called ChatApplication. Next, we will have the clients themselves, who will implement the Manager's event called, evtReceiveText, which is an event raised to all clients when anyone sends any message.

Now, for those who've done some remoting, I'm not going to use a config file (an XML file to configure the application's name and port, etc), but rather I'll be using these two:

On the client side, to get the Manager object (more comments on as we go on):
theManager = CType(Activator.GetObject(Type.GetType("InBetween.Manager,InBetween"), "http://UP:7777/ChatApplication"), InBetween.Manager)

On the server side, to register the well known service (more comments on as we go on):
System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownServiceType( _
Type.GetType("InBetween.Manager, InBetween"), _
"ChatApplication", WellKnownObjectMode.Singleton)

Using the code (Manager.vb)

 

(Note: I've included the .config files, just in case you want to try using them)

1. To start, create an empty solution.
2. Add a new class library project called InBetween.
3. Change the default .vb name to Manager.vb
4 . Copy the code below (Be sure to read the comments as we go on)

This guy down here is the remotable object.

    

Imports System
'We are going to declare an event delegate
'Event delegates sound really big... but what this is doing is that:
' "I want to be able, from this class, to raise a type of an event called 'ReceiveText..."
' "And, I want those who use Manager class to handle that event"
' "...Now, I'm going to pass username As String and text As String."
' "It's gonna be up to you, how you're going to handle it"
Public Delegate Sub ReceiveText(ByVal username As String, ByVal text As String)

Public Class Manager
Inherits MarshalByRefObject

'Why inherit MarshalByRefObject?
'Enables access to objects across application domain boundaries
'in applications that support remoting.
'Src: .NET Framework Class Library MarshalByRefObject Class [Visual Basic]
'Let's break it down (in simple english)...
'MarshalByRefObject is the means which allows objects like this class here, to
'communicate across boundaries, via remoting.
'An application domain is a partition in an operating system process where one or more applications reside.

'What's this? I thought we already declared an event handler?
'Here's where we need to declare the event itself.
'Delegates, as its name suggests are 'ambassadors' who advertises this event
'That's why in our Client.vb, we say "theManager.evtReceiveText", and not 'theManager.ReceiveText'
Public Event evtReceiveText As ReceiveText

Public Overrides Function InitializeLifetimeService() As Object
'This function, if overriden, allows us to tell the Manager object how long
'it should live. If by any reason we'd like to have it stay a 'lil longer, we renew it and so forth
'We won't do anything here. So what happens is that
'the Manager object is governed by a default lifetime.
Return Nothing
End Function


Public Function SendText(ByVal username As String, ByVal text As String)
'Later in the client.vb code, you would see that chat clients (like John Doe), will
'raise thise event by calling SendText with the appropriate paramaters.
'This event is then propagated to ALL clients, like Jones and so forth.
'On Jones' PC (for example), Client.vb would handle this event by displaying something like
'"John: yada yada" on the txtReceivedMsgs.
'Of course John's client window sould also show the same
RaiseEvent evtReceiveText(username, text)
End Function

Public Function getHash() As String
'this is just a handy function to reaffirm that all your clients are communicating
'with a ONE and only Manager object
'Which means (in simple English),
'John and the Jones will see the very same hash code which was assigned to the Manager object
Return Me.GetType.GetHashCode().ToString
End Function

End Class

 

Using the code (Server.vb)


1. Add a new Console Application project called Server, or whatever you want to call it.
2. Change the default .vb name to Server.vb
3. Don't forget to add a reference to InBetween, 'cause we're going to make the first ever call to it and calling its getHash method.
4 . Copy the code below (Be sure to read the comments as we go on)

This is the guy that's in charged of registering our service, the ChatApplication. We notice that we create a singleton as shown below.


Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Http
Imports System.Runtime.Remoting
Imports System
Imports InBetween


public class Server

Public Shared Sub Main()
Dim server1 As Server
server1 = New Server()
End Sub

Public Sub New()

'Create a HTTP channel for our use
'We'll 'talk' on this port
'IMPORTANT: Make sure you don't have anything running on this channel!
Dim chan As IChannel = New HttpChannel(7777)

'Register it
ChannelServices.RegisterChannel(chan)

'I could have read the config from an xml file with :
'System.Runtime.Remoting.RemotingConfiguration.Configure(your.config.file)
'(XML format)
'Refer .NET Framework Class Library RemotingConfiguration.Configure Method [Visual Basic]
'BUT somehow, I just couldn't make it work! So I went for this great 1 line code shown below:

'Notice these things:
'1. We are registering a service: RegisterWellKnownServiceType
'2. It's of type: Type.GetType("InBetween.Manager, InBetween")
' InBetween is the namespace, Manager is the class
'3. We're calling that application, ChatApplication
'4. It's of type: Singleton
' Why Singleton and not singlecall? If u chose singlecall,
' everyone client (John and the Jones) would be creating their own Manager objects
' which would mean no message ever gets across to anyone
System.Runtime.Remoting.RemotingConfiguration.RegisterWellKnownServiceType( _
Type.GetType("InBetween.Manager, InBetween"), _
"ChatApplication", WellKnownObjectMode.Singleton)

'I registered the Manager class and called getHash
'Read Manager.vb for more details on getHash
Dim Manager1 As New Manager()
Console.WriteLine("The Manager object's ID:" & Manager1.getHash())
System.Console.WriteLine("Hit ENTER to exit...")

'We don't want this object to die out too fast, so we just put a
'ReadLine here to sustain the object's lifetime
System.Console.ReadLine()

End Sub
End Class

Using the code (Client.vb)

Now, here's where we design the client.


1. Add a new Windows Application project called Client.
2. Change the default .vb name to Client.vb. If you're planning on copy and pasting, skip to 5.
3. Add two multilined textbox called txtReceivedMsgs and txtMsgToSend to handle received messages and to type messages into, respectively
4. Add a simple button, btnSend
5. Again, add a reference to InBetween and System.Runtime.Remoting. We need the latter too, because we're going to need to create a HTTPChannel object.
5. Copy the code below, make sure you name the variables as above (if you've created the interface yourself). (Be sure to read the comments as we go on)

 



Imports System.Runtime.Remoting.Channels.Http

Public Class Client
Inherits System.Windows.Forms.Form

Private theManager As InBetween.Manager

#Region " Windows Form Designer generated code "

Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()

'Add any initialization after the InitializeComponent() call

Dim chan As HttpChannel

'Create a HTTP channel for our use
'IMPORTANT: Make sure you don't have anything running on this channel!
chan = New HttpChannel("8888")

'Registers a channel with the channel services.
System.Runtime.Remoting.Channels.ChannelServices.RegisterChannel(chan)

'Creates a proxy for a currently running remote object
'This remote object is the our InBetween.Manager's instance
'NOTE: Change 'UP' to your Chat server's name
'http://UP:7777/ChatApplication
theManager = CType(Activator.GetObject(Type.GetType("InBetween.Manager,InBetween"), "http://UP:7777/ChatApplication"), InBetween.Manager)

'Add our event handler here
'In other words, tell this fellar, "when you receive an event called evtReceiveText
'(of type InBetween.Manager), then use the sub called HandleReceivedMsg
'to handle it
Try
AddHandler Me.theManager.evtReceiveText, AddressOf Me.HandleReceivedMsg
Catch e1 As Exception
'Our simple exception handler
MessageBox.Show(e1.Message)
End Try

'Cosmetic, I'm against it, but...
'(This displays a caption on your client window that says "Client on <PC NAME>")
Me.Text = "Client on " & Windows.Forms.SystemInformation.ComputerName()

'Now, you would notice that the getHash(), will return a string that identifies
'the 'theManager's hash code. This Hash code will appear on ALL clients.
'Why? Simple, we are dealing with ONE and only ONE instance of InBetween's Manager class
'We specified singleton on the server (Module1.vb), remember?
'It's easy to remember, a 'single' 'ton', "SINGLE-TON"
MessageBox.Show(Me.theManager.getHash())
End Sub

'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents txtReceivedMsgs As System.Windows.Forms.TextBox
Friend WithEvents btnSend As System.Windows.Forms.Button
Friend WithEvents txtMsgToSend As System.Windows.Forms.TextBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.btnSend = New System.Windows.Forms.Button()
Me.txtReceivedMsgs = New System.Windows.Forms.TextBox()
Me.txtMsgToSend = New System.Windows.Forms.TextBox()
Me.SuspendLayout()
'
'btnSend
'
Me.btnSend.Location = New System.Drawing.Point(280, 160)
Me.btnSend.Name = "btnSend"
Me.btnSend.TabIndex = 0
Me.btnSend.Text = "&Send"
'
'txtReceivedMsgs
'
Me.txtReceivedMsgs.Location = New System.Drawing.Point(0, 8)
Me.txtReceivedMsgs.Multiline = True
Me.txtReceivedMsgs.Name = "txtReceivedMsgs"
Me.txtReceivedMsgs.ReadOnly = True
Me.txtReceivedMsgs.Size = New System.Drawing.Size(360, 88)
Me.txtReceivedMsgs.TabIndex = 1
Me.txtReceivedMsgs.Text = ""
'
'txtMsgToSend
'
Me.txtMsgToSend.Location = New System.Drawing.Point(0, 104)
Me.txtMsgToSend.Multiline = True
Me.txtMsgToSend.Name = "txtMsgToSend"
Me.txtMsgToSend.Size = New System.Drawing.Size(360, 48)
Me.txtMsgToSend.TabIndex = 2
Me.txtMsgToSend.Text = ""
'
'Client
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(360, 189)
Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.txtMsgToSend, Me.txtReceivedMsgs, Me.btnSend})
Me.MaximizeBox = False
Me.Name = "Client"
Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
Me.Text = "Client"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
'What happenning here?
'Once we press our 'Send' button,
'we raise an event via SendText method of Manager (InBetween)
'Then just, erase our textbox - txtMsgToSend
'Easy isn't it?
'To follow the event, peek at InBetween's Manager's SendText method
Me.theManager.SendText(Windows.Forms.SystemInformation.ComputerName, Me.txtMsgToSend.Text)
txtMsgToSend.Text = ""
End Sub

Sub HandleReceivedMsg(ByVal username As String, ByVal text As String)
'Ok, here's what happens...
'John Doe sends u a message, the Manager object raises an event,
'your client intercepts it, and execution drops down here...
'You then append the text here...
'"... and I thought chat programs were hard..." well anyway, here's the line that does it
Me.txtReceivedMsgs.AppendText(username & " : " & text & vbCrLf)
End Sub

Private Sub Client_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing

Try
'Ok, let's undo what we've done
'We've added a handler, (remember?), so now we need to remove it
'You basically do this, ...
RemoveHandler theManager.evtReceiveText, // AddressOf Me.HandleReceivedMsg
Catch e1 As Exception
'Exception handling for... err, simple ppl like us...
MessageBox.Show(e1.Message)
End Try
End Sub

Private Sub Client_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

End Sub
End Class

Run It! (Conclusion)

1. Build the solution. You will be prompted to set the startup object, just do so.
2. As you're waiting, note these points:

  • We could have used the .config files, but I prefer to code it to show you how to do without the .config
  • As each client window loads up, you'll see the same hash code. It's the hash code of the singleton Manager object.
  • We're using the same http port (7777) on both side (client and server). We could use TCP if we wanted to. You'd better make sure John Doe's ftp server (or any other application) isn't running at that port too (at the same time)!
  • Our Well-known object was exposed on the server end

3. Just before you really run it, place the server.exe into the same directory as client.exe. Place other clients on other PCs
4. Run the server.exe first, then, all the clients.
5. Chat!

So what's the conclusion?

  • The most important thing to note is: We've done a server activation
  • MSDN says "... Server-activated objects are objects whose lifetimes are directly controlled by the server. The server application domain creates these objects only when the client makes a method call on the object, not when the client calls new (New() in Visual Basic) or Activator.GetObject(); this saves a network round trip solely for the purpose of instance creation. Only a proxy is created in the client application domain when a client requests an instance of a server-activated type... There are two activation modes (or WellKnownObjectMode values) for server-activated objects, Singleton and SingleCall..." .NET Framework Developer's Guide Server Activation [Visual Basic]
  • Our first method call to the object was in Server.vb. We could also have made the first call from client.vb. Try this, remove the comment on theManager = New InBetween.Manager() in client.vb, and in server.vb, comment these:
    Dim Manager1 As New Manager()
    Console.WriteLine("The Manager object's ID:" & Manager1.getHash())
    So you see, it still works the same... I had to make the first call to getHash() in Server.vb because I wanted to get the Hash code on server.vb to display. So let me recap: the reason why we call this Server activated is because our object's lifetime was directly controlled by the server via Singleton activation. We didn't instantiate anything by saying Dim Manager1 As New Manager(), that just registered the object. The actual object existed only after we made the method call.

 

Points of Interest

Strange thing to note: The first client to be executed, must be run from the same directory of the server.exe! Subsequent clients need not be started in the same directory as server.exe. Yes that's strange, otherwise, you'd get this silly error which makes no sense:
System.IO.FileNotFoundException
File or assembly name Client , or one of its dependencies, was not found.


Yes, it's a known problem, you might want to read more on this here: http://www.dotnet247.com/247reference/msgs/12/63594.aspx

I might want to come out with a good walkaround that later on, but till then, all the best in remoting! Spend a sec' to rate me, will ya? Thanks

Etc

  • For those who've done COM before, "what the difference between .Net remoting and remotely activated COM?&quo; // t;. Unlike COM, remoting does not start the host or server application for you. This is an important difference between .NET remoting and remote activation in COM.
  • MSDN calls our Manager.vb a remotable type. Our Server.vb is the host application
  • Your host application domain is not limited to our simple chat program, but they may be Windows Services, console applications, Windows Forms applications, Internet Information Services (IIS) processes, or ASP.NET applications.
  • General Host Tasks (eg. what you should think about when coding your own host)
    • What's my host application domain going to be like? (Windows Services, console applications, Windows Forms applications, Internet Information Services (IIS) processes, or ASP.NET applications)
    • Which activation model should I use? (Client/Server activation)
    • Choose a channel (HTTP or TCP) and a port. Register it using ChannelServices.RegisterChannel. Remember, you can't use the same port as Uncle Joe's FTP server...
  • General Client Tasks (eg. what you should think about when coding your own client)
    • What's my client application domain going to be like? (Windows Services, console applications, Windows Forms applications, Internet Information Services (IIS) processes, or ASP.NET applications)
    • Which activation model should I use? (Client/Server activation)
    • Should I use the client activation URL (eg. ProtocolScheme://ComputerName:Port/PossibleApplicationName
      ) or the well-known object URL (eg. ProtocolScheme://ComputerName:Port/PossibleApplicationName/ObjectUri) of the remote type.
    • Choose a channel (HTTP or TCP) and a port. Register it using ChannelServices.RegisterChannel.
  • If you want to try to use the .config file, which I don't like, bear in mind that most of the problems using .NET remoting occur because some of these settings are either incorrect or do not match the configuration settings for client applications. It is very easy to mistype a name, forget a port, or neglect an attribute. If you are having problems with your remoting application, check your configuration settings first.

History

Friday 13, 2003: Uploaded first version.
Saturday 14, 2003: Uploaded second version (due to great ratings).
Monday 16, 2003: Added the Etc section

winzip iconDownload article

Note: Due to the size or complexity of this submission, the author has submitted it as a .zip file to shorten your download time. Afterdownloading it, you will need a program like Winzip to decompress it.

Virus note:All files are scanned once-a-day by Planet Source Code for viruses,but new viruses come out every day, so no prevention program can catch 100% of them.

FOR YOUR OWN SAFETY, PLEASE:
1)Re-scan downloaded files using your personal virus checker before using it.
2)NEVER, EVER run compiled files (.exe's, .ocx's, .dll's etc.)--only run source code.

If you don't have a virus scanner, you can get one at many places on the net including:McAfee.com

 
Terms of Agreement:   
By using this article, you agree to the following terms...   
1) You may use this article in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.   
2) You MAY NOT redistribute this article (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
3) You may link to this article from another website, but ONLY if it is not wrapped in a frame. 
4) You will abide by any additional copyright restrictions which the author may have placed in the article or article's description.


Other 2 submission(s) by this author

 

 
Report Bad Submission
Use this form to notify us if this entry should be deleted (i.e contains no code, is a virus, etc.).
Reason:
 
Your Vote!

What do you think of this article(in the Beginner category)?
(The article with your highest vote will win this month's coding contest!)
Excellent  Good  Average  Below Average  Poor See Voting Log
 
Other User Comments
6/13/2003 9:13:25 AM:Eric Tomlinson
I think the tutorial would be really godd except for the formatting of the text. It made it hard to read. Next time I would suggest using HTML formatting to make it more readable. Thanks for posting.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
6/13/2003 10:15:59 AM:overcomers
Rectified. Pls rate it :) thanks
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
6/13/2003 4:54:00 PM:Niknak!!
Ill give you 5 for the severity if your image!, you trying to give me nightmares?
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
6/13/2003 6:15:32 PM:D. de Haas
Formating looks much better since my last visite to this post. Great work!! 5x
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
6/13/2003 11:59:09 PM:overcomers
hey thanks for all your comments! I'm gonna write more soon
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
6/16/2003 4:03:01 AM:Daniel Ang C. M.
added etc section
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
6/24/2003 2:51:02 AM:Daniel Ang C. M.
I'm working no the fix now, in C# this time, and hope to run it on v1.1
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
8/2/2003 2:18:49 AM:
I am getting this error message "Type System.DelegateSerializationHolder and the types derived from it (such as System.DelegateSerializationHolder ) are not permitted to be serialized at this security level." I made a full trust for the client , server and inbetween. I put the client in the server bin directory. I run the server first , then the client in the server directory and got that message on the load of the client. Any Clue will be appreciated
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
8/19/2003 10:53:56 AM:
I think you need to calm down a bit in your explanations. You tend to flit from one definition to another with no continuity, and you're using terms before defining what they mean. Try looking at your work from a completely neutral standpoint and I think you'll realise how difficult it may be to follow for some people.
Keep the Planet clean! If this comment was disrespectful, please report it:
Reason:

 
Add Your Feedback!
Note:Not only will your feedback be posted, but an email will be sent to the code's author in your name.

NOTICE: The author of this article has been kind enough to share it with you.  If you have a criticism, please state it politely or it will be deleted.

For feedback not related to this particular article, please click here.
 
Name:
Comment:

 

Categories | Articles and Tutorials | Advanced Search | Recommended Reading | Upload | Newest Code | Code of the Month | Code of the Day | All Time Hall of Fame | Coding Contest | Search for a job | Post a Job | Ask a Pro Discussion Forum | Live Chat | Feedback | Customize | .Net Home | Site Home | Other Sites | About the Site | Feedback | Link to the Site | Awards | Advertising | Privacy

Copyright© 1997 by Exhedra Solutions, Inc. All Rights Reserved.  By using this site you agree to its Terms and Conditions.  Planet Source Code (tm) and the phrase "Dream It. Code It" (tm) are trademarks of Exhedra Solutions, Inc.