C++Builder 5 Developers Guide
TCP/IP SocketConnection
So far, you've mainly worked with the TDCOMConnection component and the TWebConnection component. However, DataSnap can also employ a third protocol: TCP/IP (plain sockets). This is done by using the TSocketConnection component (the third of the Connection components available on the DataSnap tab of the Component Palette from C++Builder 6 Enterprise).
If you don't have an NT domain server available on your network, you should probably not try to use DCOM at all and instead should use plain TCP/IP. A socket connection will work even if no NT server is in the equation, and it is usually much easier to set up than a DCOM connection. However, security is much more difficult to enforce on a socket connection (unlike the TWebConnection component, for example).
You can easily convert either SimpleDataSnapClient or DataSnapClient into a TCP/IP application. You don't even need to make any changes to your DataSnap servers to make it work. To get started building your sockets-based DataSnap program, run the ScktSrvr.exe program found in the CBuilder6\Bin directory on the server machine. This program must be running on the server or this system will not work. Note that ScktSrvr.exe can either be run as a normal application or be used as an NT service (using the -install and -uninstall command-line parameters).
Drop a TSocketConnection component from the DataSnap page of the Component Palette on the main form of the DataSnapClient application. Set its Address property to the IP address of the machine where the DataSnapServer application resides. This can be a remote machine or your current machine (such as localhost ). Fill in the ServerName property, just as you did in the DCOM example earlier in this chapter, by dropping down the ServerName combo box and selecting the DataSnapServer.CustomerOrders DataSnap Server. You should now be able to test your connection by setting the Connected property of the TSocketConnection component to true . As I explained earlier, you should not leave the Connected property set to true at design time.
Assuming you have dropped down a TSocketConnection component on the form and set its ServerName property correctly, you can drop a new TButton component, set its Name property to ButtonSocket , Caption to Socket , and write the event handler code as seen in Listing 20.2:
Listing 21.2 SocketConnection to Remote Machine
void __fastcall TForm1::ConnectTCPIP1Click(TObject *Sender) { AnsiString S; if (InputQuery("Enter Machine Name or IP-Address:", "Machine Name/IP-Address", S)) { SocketConnection1->Address = S; ClientDataSet1->RemoteServer = SocketConnection1; ClientDataSet1->Active = true; } }
When the user clicks on the Socket button, he is prompted for the IP address of the machine where the server resides. Assuming your system is set up correctly, you can also pass in the human-readable equivalent of that IP address, such as localhost or ” in my case ”www.eBob42.com.
The code sets the Address property of the TSocketConnection component to the address supplied by the user. It then changes the RemoteServer property of the TClientDataSet so that it no longer points at the TDCOMConnection component, but at that TSocketConnection component. Finally, it sets the Active property of the TClientDataSet to true . Setting the Active property to true will automatically cause the TSocketConnection.Connected property to be set to true as well, as you've seen earlier.
At this stage, you should be fully connected to your server and viewing your data. This approach will work equally well whether the server is on the same machine or on a remote machine. Furthermore, you don't need an NT domain server or even an NT server, though I always recommend that you use one when working with DataSnap.
Note that the DataSnap server does not have to be changed to connect to a client using DCOM or sockets (TCP/IP). In fact, after you have a working DataSnap server, you only need to run it to enable it to register itself (so you can locate it and connect to it from a DataSnap client). This COM-specific Registry is done by the inherited UpdateRegistry call, and is performed by all versions of DataSnap. It's actually quite convenient because if you want to move the server application to another location (on the same machine), you only need to rerun it to reregister itself and enable clients to connect to it.
Usually, I write DataSnap applications that communicate using DCOM. However, in some cases you might want to use plain sockets instead. A regular remote data module can communicate using sockets, provided you've left that particular communication protocol enabled in the UpdateRegistry method. Clients need to connect to the remote data module using the SocketConnection component. However, for a connection to be made to the DataSnap application server, you also need to run the socket server on the server machine. Using C++Builder 4, you had two socket server applications: ScktSrvr.exe (the socket server) or ScktSrvc.exe (the NT service edition of the socket server). In C++Builder 5 and 6, these two are combined in a single ScktSrvr.exe that can either be run as a normal application or be used as an NT service (using the -install and -uninstall command-line parameters).
Registered Servers
As I mentioned before, the C++Builder 5 and 6 ScktSrvr checks the Registry to see if a DataSnap server has enabled the socket communication protocol (that is, whether the EnableSocket field of the regObj has been assigned to true inside the UpdateRegistry() function). For C++Builder 4 DataSnap servers, this isn't present, which means that if you upgrade a C++Builder 4 DataSnap server to C++Builder 5 or 6, you must not forget to include a new UpdateRegistry method. If, for any reason, the new DataSnap server doesn't register itself as using the socket communication protocol, you can always use the C++Builder 6 socket server (and not the C++Builder 4 socket server). In the Connections menu you can specify that you don't want Registered Object Only (you want to see unregistered objects as well, as can be seen in Figure 21.1).
Figure 21.1. Borland socket server looking at registered objects only.
This change will not take affect until the socket server is restarted, but then you can see C++Builder 6 DataSnap servers using the TSocketConnection component ” registered or not.
A final new feature regarding the TSocketConnection component has to do with callbacks. TDCOMConnection components always support callbacks, and TWebConnection components never support callbacks. With a TSocketConnection component you can specify using the SupportCallbacks property, whether the TSocketConnection component will marshal calls from the DataSnapServer to the DataSnapClient over an interface supplied as a callback. If you don't want to do that, you can set SupportCallbacks to false (it's true by default). Setting it to false has the advantage that you then need only Winsock 1 support to deploy your DataSnapClient, whereas otherwise (with SupportCallbacks set to true ) you need Winsock 2 or higher. Because Windows 95 doesn't include Winsock 2 by default, this means one less deployment problem (believe it or not there are still clients out there using Windows 95).
Object Broker
You've now seen three possible connection components that exist in C++Builder Enterprise: TDCOMConnection , TWebConnection , and TSocketConnection all connecting to a single DataSnap server application. However, sometimes you don't have a single DataSnap server to connect to, but multiple DataSnap servers. Reasons for having multiple DataSnap servers can be diverse, but most often this is done for load balancing and failover. If one server goes down, others can take over, and having 10 servers all over the world usually results in fewer bottlenecks than having one big server.
Imagine having to determine at the client side which of these DataSnap Servers to connect to. You'd need to know exactly which servers are available (or you might miss one ”maybe the last one that's available at the time) and how to connect to them. In an ideal world, you wouldn't want all your clients to know about this. Fortunately, DataSnap offers a helpful hand in this case, by means of the concept called Object Brokering.
With Object Brokering, you make a connection from the client to a server without knowing which server you'll end up with. Each of the three connection components has a property called ObjectBroker . This property can be used to connect to a component derived from TCustomObjectBroker . It will then be responsible for telling the connection component which server to use (by specifying the ServerName or ServerGUID ). Note that when you actually use an ObjectBroker , the local values specified for the ServerName and ServerGUID properties will be ignored as far as your application is concerned ; ObjectBroker will supply you with dynamic values at runtime.
As an example of how to implement your own Object Brokering techniques, C++Builder Enterprise comes with a TSimpleObjectBroker component (found on the DataSnap tab of the Component Palette).
TSimpleObjectBroker itself contains two interesting properties. Servers contains a list of available servers, for each of which you can specify the ComputerName , the Port (211 by default), and Enabled . Note that you as a developer must make sure that this list is filled and maintained properly. If you add a new server or a server goes down, you must update the list.
The second property is LoadBalanced . As the name indicates, this property tries to ensure that the servers are load balanced, or at least that a request is balanced among the servers. The technique used here is based on a random generator. When LoadBalanced is set to true , each connection component will be connected to a random server from the list. When LoadBalanced is set to false (the default), each connection component on the client application will be connected to the first server on the list.
The TSimpleObjectBroker component is implemented in unit ObjBrkr (found in the $(BCB)\Source\Vcl directory) and contains a fairly simple algorithm. Picking a random server isn't such a bad idea, but obviously it's not really intelligent , either. If you ever need to write your own Object Broker algorithm, TSimpleObjectBroker might be a good place to start.
One final word on Object Brokering: After a connection component is connected to a DataSnap server, it will remain connected to that particular server until the Connected property is set to false again. When you reconnect (set Connected back to true ), you might end up with a different server.
|
|
Top |