Click here to Skip to main content
Click here to Skip to main content
Go to top

Remote Objects Part 2

, 1 Apr 2002
Rate this:
Please Sign up or sign in to vote.
This article shows how to create a remote server and MDI window Remote Client using remote objects
<!-- Download Links --> <!-- Add the rest of your HTML here -->

Introduction

This article shows how to create a remote server and MDI window Remote Client using remote object. The remote server can be used as Auction Server and Real Time Data and Information Server.

.NET Remoting is a technology that can be used to allow .NET applications to communicate to each other, it is does not matter to cross a network with firewall security, or over the Internet. The Remote object can be used to transport messages between remote objects using different transportation protocols, serialization formats, and object lifetime schemes.

An object derived from MarshalByRefObject can be used as Remotable objects. Remotable objects can be accessed by other application domain using a proxy or they can be passed to another application domain by value or by reference.

In this article, the clients register their callback by passing their object to the server. This waylet the server control the client easier than the way that registers callback using delegate and event (See my article Remote Object Part1). In this way, it is much easier for the serverto handle the registration and the situation that the clients closed without call the server's unregister function.

Fig 1

Fig 2

Fig 3

Fig 4

The program includes three parts.

  1. Window Server with a remote object that supports Auction, News, Market News, Real time Stocks Data. (See Fig 1)
  2. MDI Window Client with a remote object that used to register user to the remote server and display the information that is coming from the server. (See Fig 2, 3)
  3. Pusher can be used to send all kind of information to sever then the server send all the information to the registered users. (See Fig 4)

Client Host:

The client open a remote channel and pass their remote objects to the server to register their callback function and keep a cookie to cleanup the register when the client is closed. This gives the remote server more flexibility and more control to the clients than the method described in the Remote Object Part1.

public void ConnctServer()                                                     
{                                                                              
    ......                                                            
    HttpChannel chan = new HttpChannel(Int32.Parse(MyDlg.port));       
    ChannelServices.RegisterChannel(chan);                             
    SrvObj = (RemoteServer)Activator.GetObject(                        
                              typeof(WRemoteServer.RemoteServer),              
                              "http://localhost:8085/RemoteObj");              
                                                                               
    if (SrvObj == null)                                                
        lb.Items.Add("Can't connect to server");                     
    else                                                               
        registerClient(MyDlg);                                       
}  

private void registerClient(Login MyDlg)                                       
{                                                                              
            RemotingConfiguration.RegisterWellKnownServiceType(                
            Type.GetType("WRemoteClient.RemotingClient,                        
                                    RemotingClient"),                          
                                    "ClientObj",                               
                                    WellKnownObjectMode.Singleton);            
                                                                               
            string url=String.Format("http://localhost:{0}/                    
                                    ClientObj", MyDlg.port);                   
            CltObj = (RemotingClient)Activator.GetObject(                      
                                    typeof(WRemoteClient.RemotingClient),      
                                    url);                                      
                                                                               
            string rtnMsg;                                                     
            Cookie = SrvObj.SinkClientObj(CltObj, MyDlg.srvType,               
                                  MyDlg.username, MyDlg.password,out rtnMsg);  
                                                                               
            CltObj.InvokeFormMethod += new                                     
                                    CFormEventHandler(OnMsgHandler);           
                                                                               
            lb.Items.Add(MyDlg.username + ":" + MyDlg.srvType+" register is "  
                                                                + rtnMsg);

Client Remote Object:

This object is small and only used to handle the callback from the Remote server. Passing it as value to Remote object is acceptable.

namespace WremoteClient                                                        
{                                                                              
    public delegate void CFormEventHandler(object sender, RemoteEventArgs e);  
                                                                               
      public class RemotingClient : MarshalByRefObject                         
      {                                                                        
            public event CFormEventHandler InvokeFormMethod;                   
            [OneWay]                                                           
            public void ClientReciever(string msg, string newsTitle,           
                              string newsContents, int type)                   
            {                                                                  
                  RemoteEventArgs e = new RemoteEventArgs(msg,"","",           
                              newsTitle, newsContents, type);                  
                  if(InvokeFormMethod != null)                                 
                        InvokeFormMethod(this, e);                             
            }                                                                  
      }                                                                        
}       

Server Host:

private void startServer()                                                     
{                                                                              
      ChannelServices.RegisterChannel(new HttpChannel(8085));                  
                                                                               
      RemotingConfiguration.RegisterWellKnownServiceType(                      
                  Type.GetType("WRemoteServer.RemoteServer,RemoteServer"),     
                  "RemoteObj", WellKnownObjectMode.SingleCall);                
                                                                               
      SrvActObj = (RemoteServer)Activator.GetObject(                           
                              typeof(WRemoteServer.RemoteServer),              
                              "http://localhost:8085/RemoteObj");              
                                                                               
      SrvActObj.CreateUsrInfo();                                               
      usrGrid.DataSource = RemoteServer.usrMgrTab;                             
}     

Server Remote Object:

This object supports four function, Auction, Real-Time Stock information , News and Market News. It includes four SortedList to hold the registered client object that is used to callback when the data is available. This makes the server to call the methods of the clients and to pass a more complex data type to the clients every easy. The proxy automatically converts all kind of data type between the call.

The client can register their request by call the function SinkClientObj and call UnSinkObj to clean the register on the server.

namespace WremoteServer                                                        
{                                                                              
      // Define the event                                                      
      public delegate void ServerEventHandler (object sender,                  
                                          RemoteEventArgs e);                  
                                                                               
      public class RemoteServer : MarshalByRefObject                           
      {                                                                        
            public static event ServerEventHandler InvokeHostForm;             
            private static SortedList StockObjHolder = new SortedList();       
            private static SortedList NewsObjHolder = new SortedList();        
            private static SortedList AuctionObjHolder = new SortedList();     
            private static SortedList MarketObjHolder = new SortedList();      
                                                                               
            public  static DataTable usrMgrTab = new DataTable("UsrMgr");      
                                                                               
            public string SinkClientObj(Object obj, string srvType,            
                        string username, string password, out string rtnMsg)   
            {                                                                  
                  bool chkStatus=false;                                        
                  chkStatus = CheckUser(username, password, srvType);          
                  if(chkStatus)                                                
                  {                                                            
                        rtnMsg = "Ok";                                         
                        switch(srvType)                                        
                        {                                                      
                              case "Stock":                                    
                                    lock(this)                                 
                                    {                                          
                                    if(!StockObjHolder.ContainsKey(username))  
                                          StockObjHolder.Add(username,         
                                                     (RemotingClient) obj);    
                                    else                                       
                                    {                                          
                                          StockObjHolder[username] =           
                                                      (RemotingClient) obj;    
                                                rtnMsg = "Ok But it replace    
                                                 previous registerd one!";     
                                    }                                          
                                    }                                          
                                    break;                                     
                              case "News":                                     
                                    lock(this)                                 
                                    {                                          
                                    if(!NewsObjHolder.ContainsKey(username))   
                                          NewsObjHolder.Add(username,          
                                                      (RemotingClient) obj);   
                                    else                                       
                                    {                                          
                                          NewsObjHolder[username] =            
                                                      (RemotingClient) obj;    
                                                rtnMsg = "Ok But it replace    
                                                 previous registerd one!";     
                                    }                                          
                                    }                                          
                                    break;                                     
                              case "Auction":                                  
                                    lock(this)                                 
                                    {                                          
                                   if(!AuctionObjHolder.ContainsKey(username)) 
                                          AuctionObjHolder.Add(username,       
                                                     (RemotingClient) obj);    
                                    else                                       
                                    {                                          
                                          AuctionObjHolder[username] =         
                                                      (RemotingClient) obj;    
                                                rtnMsg = "Ok But it replace    
                                                 previous registerd one!";     
                                    }                                          
                                    }                                          
                                    break;                                     
                              case "Market News":                              
                                    lock(this)                                 
                                    {                                          
                                    if(!MarketObjHolder.ContainsKey(username)) 
                                          MarketObjHolder.Add(username,        
                                                      (RemotingClient) obj;    
                                    else                                       
                                    {                                          
                                          MarketObjHolder[username] =          
                                                      (RemotingClient) obj;    
                                                rtnMsg = "Ok But it replace    
                                                 previous registerd one!";     
                                    }                                          
                                    }                                          
                                    break;                                     
                        }                                                      
                        RemoteEventArgs e = new RemoteEventArgs(rtnMsg,        
                                                username, srvType, "", "",0);  
                                                                               
                        // Fire server form event                              
                        if(InvokeHostForm != null)                             
                              InvokeHostForm(this, e);                         
                  }                                                            
                  else                                                         
                        rtnMsg = "Fail";                                       
                  return username;                                             
            }                                                                  
            public void UnSinkObj(string Cookie, string serType, bool client)  
            {                                                                  
                  if(client)                                                   
                  {                                                            
                        if(srvType == "")                                      
                        {                                                      
                              StockObjHolder.Remove(Cookie);                   
                              NewsObjHolder.Remove(Cookie);                    
                              AuctionObjHolder.Remove(Cookie);                 
                              MarketObjHolder.Remove(Cookie);                  
                        }                                                      
                        else                                                   
                        {                                                      
                              switch(srvType)                                  
                              {                                                
                                    case "Stock":                              
                                          StockObjHolder.Remove(Cookie);       
                                          break;                               
                                    case "News":                               
                                          NewsObjHolder.Remove(Cookie);        
                                          break;                               
                                    case "Auction":                            
                                          AuctionObjHolder.Remove(Cookie);     
                                          break;                               
                                    case "Market News":                        
                                          MarketObjHolder.Remove(Cookie);      
                                          break;                               
                        }                                                      
                  }                                                            
                  string tmp =string.Format("{0} is unregistered!", Cookie);   
                  RemoteEventArgs e = new RemoteEventArgs(tmp, "", "", "",     
                                                                  "",0);       
                                                                               
                  // Fire server form event                                    
                  if(InvokeHostForm != null)                                   
                        InvokeHostForm(this, e);                               
            }                                                                  
                                                                               
            public void SendMsgToClient(int msgType, string title, string      
                                                      contents, string msg)    
            {                                                                  
                  RemoteEventArgs e = new RemoteEventArgs("", "", "", title,   
                                                            contents,0);       
                  string removeKey="no";                                       
                  switch(msgType)                                              
                  {                                                            
                        case 1:                                                
                              foreach(string key in NewsObjHolder.Keys)        
                              {                                                
                                    try                                        
                                    {                                          
                                         clientObj =                           
                                         (RemotingClient)NewsObjHolder[key];   
                                         clientObj.ClientReciever("", title,   
                                                         contents, msgType);   
                                    }                                          
                                    catch { removeKey = key;}                  
                             }                                                 
                             break;                                            
                        case 2:                                                
                             foreach(string key in MarketObjHolder.Keys)       
                             {                                                 
                                    try                                        
                                    {                                          
                                         clientObj =                           
                                         (RemotingClient)MarketObjHolder[key]; 
                                         clientObj.ClientReciever("", title,   
                                                           contents, msgType); 
                                    }                                          
                                    catch { removeKey = key;}                  
                             }                                                 
                             break;                                            
                        case 3:                                                
                             foreach(string key in AuctionObjHolder.Keys)      
                             {                                                 
                                    try                                        
                                    {                                          
                                         clientObj =                           
                                         (RemotingClient)AuctionObjHolder[key];
                                         clientObj.ClientReciever("", title,   
                                                           contents, msgType); 
                                    }                                          
                                    catch { removeKey = key;}                  
                             }                                                 
                             break;                                            
                        case 4:                                                
                        foreach(RemotingClient rc in NewsObjHolder.Values)     
                              rc.ClientReciever(msg, "", "", msgType);         
                        foreach(RemotingClient rc in StockObjHolder.Values)    
                              rc.ClientReciever(msg, "", "", msgType);         
                        foreach(RemotingClient rc in AuctionObjHolder.Values)  
                              rc.ClientReciever(msg, "", "", msgType);         
                        foreach(RemotingClient rc in MarketObjHolder.Values)   
                              rc.ClientReciever(msg, "", "", msgType);         
                              break;                                           
                  }                                                            
                  if(removeKey != "no")                                        
                  {                                                            
                        // Remove the register that cause the exception        
                        NewsObjHolder.Remove(removeKey);                       
                        RemoteEventArgs e2 = new RemoteEventArgs(removeKey +   
                                          " is removed!", "", "", "", "",0);   
                        // Fire server form event                              
                        if(InvokeHostForm != null)                             
                              InvokeHostForm(this, e2);                        
                  }                                                            
           }                                                                   
     ...                                                          
}                    

Steps to create the sample:

  1. Compile the Remote object by running makefile.bat at RemoteObj directory.
  2. Compile the WremoteClient , the WremoteServer and the InfoPusher. You may need to change the references to these DLL.
  3. Copy all the DLL files in RemoteObj directory to the ..\bin\Debug directory or C:\WINNT\assembly directory.

Guide to the use of the functions supplied by the server

Start all three programs (may start more than one clients). The server shows there are three registered users (user1, user2 and user3) who can request different function on this server.

Connect to server on Pusher. Now you are ready to send all information to registered clients. (See Fig 4)

Click Register on the client. A dialog is opened for you to select what kind service does you wanted from server by now.

If the Stock is selected, a child form appear, you can click the button “Send real-time stock data” on the server to get real time data from a file (Don’t missing Issue.txt in Debug Directory). (See Fig 3)

If Auction is selected, a “Go to Auction” button appears. Click it to bid your items. All the data will be showed in the ListBox (See Fig 2)

If news is selected, the client host child form can only display 5 titles of the news. The oldest one will be removed. Click the title of the news, a child form appears, that displays the contents of the news (See Fig 2)

Conclusion

.Net Remoting the most advantage technology that could be used in the client/server application than the others. Remoting is very flexible, powerful and easy to program with TCP, HTTP and SOAP. (Compare with DCOM).

Note

This Demo is updated with .Net framework 1.0 version 1.0.3705.Beta2 user may need to replace all the control with Beta2 and remove some statements that are not supported by Beta2 to make it work.

If you have any comments, I would love to hear about it. You can reach me at Jibin Pan.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Jibin Pan

United States United States
No Biography provided

Comments and Discussions

 
QuestionCan't find file Pinmemberaboi23-Aug-06 0:55 
Generalthe client on another computer can't receive the message Pinmemberliaoshuangqi@163.net9-Sep-03 23:18 
GeneralSecurity Exception in framework 1.1 Pinmemberis_vlb504-Aug-03 21:41 
GeneralRe: Security Exception in framework 1.1 PinsussLars Wilhelmsen7-Nov-03 0:56 
GeneralRe: Security Exception in framework 1.1 PinmemberDale Thompson5-Dec-03 9:47 
Lars Wilhelmsen wrote:
Have you tried to set the typeLevelFilter to Full on the formatter for the channel?
 
These changes will allow the code to work with the 1.1 Framework.
 
I used the suggestions from Ingo Rammer's web page.
 

// InfoPusher/Pusher.cs old:
 
HttpChannel chan = new HttpChannel();
ChannelServices.RegisterChannel(chan);
 
// change to:
 
SoapServerFormatterSinkProvider serverProv = new SoapServerFormatterSinkProvider();
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
 
SoapClientFormatterSinkProvider clientProv = new SoapClientFormatterSinkProvider();
 
IDictionary props = new Hashtable();
 
HttpChannel chan = new HttpChannel( props, clientProv, serverProv );
ChannelServices.RegisterChannel( chan );
 
// WRempoteClient/main.cs old:
 
HttpChannel chan = new HttpChannel();
ChannelServices.RegisterChannel( chan );
registedChan = chan;
 
// change to:
 
SoapServerFormatterSinkProvider serverProv = new SoapServerFormatterSinkProvider();
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
 
SoapClientFormatterSinkProvider clientProv = new SoapClientFormatterSinkProvider();
 
IDictionary properties = new Hashtable();
properties[ "port" ] = Int32.Parse( MyDlg.port );
 
HttpChannel chan = new HttpChannel( properties, clientProv, serverProv );
ChannelServices.RegisterChannel( chan );
registedChan = chan;
 
// WRemoteServer/ChannelServer.cs old:
 
ChannelServices.RegisterChannel(new HttpChannel());
 
// change to:
 
SoapServerFormatterSinkProvider serverProv = new SoapServerFormatterSinkProvider();
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
 
SoapClientFormatterSinkProvider clientProv = new SoapClientFormatterSinkProvider();
 
IDictionary properties = new Hashtable();
properties[ "port" ] = 8085;
ChannelServices.RegisterChannel( new HttpChannel( properties, clientProv, serverProv ) );
 


 
Dale Thompson
GeneralQuestion PinmemberAnonymous20-Nov-02 7:35 
GeneralRe: Question PinmemberJibin Pan22-Nov-02 5:33 
GeneralD'oh! Pictures missing:( PinmemberAnonymous25-Mar-02 2:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140905.1 | Last Updated 2 Apr 2002
Article Copyright 2002 by Jibin Pan
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid