Connecting a Client

With the bare minimum for the server session created, you can now do the small amount of work to get a client connected to this server. While it is technically possible to add the code for the client into the same executable as the server, in order to have a dedicated server, you will want the code separated. In order to do this, you will create an entirely new second windows forms application.

The client UI will be similar to the servers. You should have one large label covering the majority of the screen. The difference is that you should leave some room for buttons along the top of the form, since you will use these buttons to have the client perform particular actions. You also will want the clients to be able to have a name for this session, and you will want this name to be changeable. For now, just create the label covering most of the form, as well as a textbox above this label where you will be able to modify the client's name.

You will also need to ensure that you have access to the shared data between the server and the client, so you will need to add a link to the shared code file you created for the server. When adding the existing item, be sure to click the small arrow on the open button, and select the Link File option if the code file is in a different folder. Otherwise, simply selecting the Open option will create a copy of the file in your local folder, and it will no longer be shared between the two applications.

With that minor plumbing out of the way, you can start writing the client code. You will first need to create your local variables:

 private Client connection = null; private bool connected = false; 

Much like the peer-to-peer session, you will need a variable to track whether or not you've been connected to a session. You also need to maintain the connection object as well. Once again, you will need to have an initialization method implemented, only this time it will only try to find existing hosts. Add the method from Listing 19.2 to your client application.

Listing 19.2 Initializing a Client Connection
 public void InitializeClient() {     // Create our client object     connection = new Client();     // Hook the events we want to listen for     connection.ConnectComplete += new         ConnectCompleteEventHandler(OnConnectComplete);     connection.FindHostResponse += new         FindHostResponseEventHandler(OnFindHost);     // Check to see if we can create a TCP/IP connection     if (!IsServiceProviderValid(Address.ServiceProviderTcpIp))     {         // Nope, can't, quit this application         MessageBox.Show("Could not create a TCP/IP service provider.", "Exiting",             MessageBoxButtons.OK, MessageBoxIcon.Information);         this.Close();     }     // Create a new address for our local machine     Address deviceAddress = new Address();     deviceAddress.ServiceProvider = Address.ServiceProviderTcpIp;     // Create a new address for our host machine     Address hostaddress = new Address();     hostaddress.ServiceProvider = Address.ServiceProviderTcpIp;     hostaddress.AddComponent(Address.KeyPort, SharedCode.DataPort);     // Set our name     PlayerInformation info = new PlayerInformation();     info.Name = textBox1.Text;     connection.SetClientInformation(info, SyncFlags.ClientInformation);     // Set up an application description     ApplicationDescription desc = new ApplicationDescription();     desc.GuidApplication = SharedCode.ApplicationGuid;     try     {         // Search for a server         connection.FindHosts(desc, hostaddress, deviceAddress, null,             0, 0, 0, FindHostsFlags.None);         AddText("Looking for sessions.");     }     catch     {         AddText("Enumeration of sessions has failed.");     } } 

There is actually quite a bit of new information here. You will need to add the implementations of AddText and IsServiceProviderValid from where you've seen them before. The minimum client will first search for existing hosts to connect to and then try to perform the connection, so you will first hook the two events shown, much like you did in the peer-to-peer sample. You also check the service provider validity before creating the addresses.

Ah, and in this instance it really is addresses. You first create the local device address, which will simply be an address with the TCP/IP service provider. However, you also want to create a distinct address for the server that will be used to try to find any sessions. You know for certain that any host you want to connect with will be run on the port specified in SharedCode.DataPort, so you add that component to the address. If you also knew the host name of the server, you could add that component to this address as well.

The next small section is completely new. Each "member" of a session in DirectPlay can have associated information attached to it, and this data can contain the name of the "player," or some set of application defined data. For this example, you will only want to set the name of the client, so you use whatever the text from the text box happens to be (which right now is probably "textbox1"). That's a horrible name for a client, so you should update the text box before you get to this code. At the end of your forms constructor, add the following line:

 textBox1.Text = System.Environment.UserName; 

This sets the text box (and thus your initial client name) to the username of your computer. A way to change this username will be added later in this chapter.

Next you set up the application description. You'll notice that the only member you need to set for this case is the application GUID. You use the shared GUID for this member, since the server and client must have the same application GUID in order to connect to one another. Finally, you make the call to FindHosts, and assuming that succeeds, update the UI to inform the user that you're searching for sessions.

ONLY SEARCHING LOCAL SUBNET

You'll notice that in this instance you did not use the FindHostsFlags.OkToQueryForAddressing flag. For this example, you can expect the server to exist on the same subnet you are on (which is the default searching area for DirectPlay). If this isn't the case for your network, you should use this flag, or add the host name of the server into a component of its address.

You will also need the two event handler methods you've declared thus far. You will find them in Listing 19.3.

Listing 19.3 Joining a Session Event Handlers
 private void OnFindHost(object sender, FindHostResponseEventArgs e) {     lock(this)     {         // Do nothing if we're connected already         if (connected)             return;         connected = true;         string foundSession = string.Format             ("Found session ({0}), trying to connect.",             e.Message.ApplicationDescription.SessionName);         this.BeginInvoke(new AddTextCallback(AddText),               new object[] { foundSession });         // Connect to the first one         ((Client)sender).Connect(e.Message.ApplicationDescription,               e.Message.AddressSender,             e.Message.AddressDevice, null, ConnectFlags.OkToQueryForAddressing);     } } private void OnConnectComplete(object sender, ConnectCompleteEventArgs e) {     // Check to see if we connected properly     if (e.Message.ResultCode == ResultCode.Success)     {         this.BeginInvoke(new AddTextCallback(AddText),             new object[] { "Connect Success." });         connected = true;         this.BeginInvoke(new EnableCallback(EnableSendDataButton),             new object[] { true } );     }     else     {         this.BeginInvoke(new AddTextCallback(AddText), new object[] {             string.Format("Connect Failure: {0}", e.Message.ResultCode) });         connected = false;         this.BeginInvoke(new EnableCallback(EnableSendDataButton),             new object[] { false } );     } } 

These methods should look familiar as they're similar to the peer-to-peer connection strategies. You first try to find any hosts available, and as soon as one is found, attempt to connect to it. With that, you are close to having the bare minimum for the client being connected. Like the server before, the only things left are calling the initialize method and disposing the connection when the application is complete. The call to dispose won't be included here, since it's already been covered for the server, and the code is identical, but make sure you do it in your application. Finally, update the main method as follows:

 static void Main() {     using (Form1 frm = new Form1())     {         frm.Show();         frm.InitializeClient();         Application.Run(frm);     } } 

With that, your client should be ready to go. Go ahead and start a server session, and then open up a client. You should see the server update its UI to say that it is hosting, and the client should look for sessions, find your server, and connect. Now you can try to add something a little more exciting.



Managed DirectX 9 Graphics and Game Programming, Kick Start
Managed DirectX 9 Kick Start: Graphics and Game Programming
ISBN: B003D7JUW6
EAN: N/A
Year: 2002
Pages: 180
Authors: Tom Miller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net