We have two buttons on our form for either hosting or connecting to an existing session. Once we try to do either of these actions, we will need to disable these buttons so that we can't try to do more than one action at a time. The event handlers for these two buttons would be private void button1_Click(object sender, System.EventArgs e) { button1.Enabled = false; button2.Enabled = false; InitializeDirectPlay(true); } private void button2_Click(object sender, System.EventArgs e) { button1.Enabled = false; button2.Enabled = false; InitializeDirectPlay(false); } As you see, they are both remarkably similar. The only difference between the two is the parameter they pass in to the InitializeDirectPlay method; one uses true to host, the other uses false to connect. We could simplify this by having each button use the same event handler: private void button_Click(object sender, System.EventArgs e) { button1.Enabled = false; button2.Enabled = false; InitializeDirectPlay((sender == button1)); } Much nicer; this eliminates the duplicated code and achieves the exact same behavior. If the sender of the event happens to be the first button (our hosting button), it will call InitializeDirectPlay with true; otherwise, it will call it with false. Hook each button's event in this way. We never actually did anything with the parameter for this method, though. We should look at that now. Before we can either host a session or connect to an existing one, we will need a way to "recognize" a session. DirectPlay includes an application description structure that will contain all of the information we need to describe an application. Let's look at the code we'll use for our application description; add this to the end of the InitializeDirectPlay method: // Set up an application description ApplicationDescription desc = new ApplicationDescription(); desc.SessionName = "MDXBookPeerSession"; desc.GuidApplication = new Guid(41039, 1702,1503,178, 101, 32, 13, 121, 230, 109, 59); The most important member of this structure is the GuidApplication member. This GUID uniquely identifies your application, and all instances of your application must use the same GUID for this member. The other member we set is the session name. This is useful for when there are many sessions available to help identify yours. You will find all of the members of the ApplicationDescription structure in Table 18.2.
With the application description created now, we are ready to get into a session. Since we need to have a session exist before we can connect to it, we will deal with the hosting code first. Add the following to the end of the initialize method: if (host) { try { // Host a new session connection.Host(desc, deviceAddress); // We can assume after the host call succeeds we are hosting AddText("Currently Hosting a session."); EnableSendDataButton(true); } catch { AddText("Hosting this session has failed."); } } As you can see, the Host call is relatively straightforward. We've used the simplest overload for our call that takes only the application description and our local address. There are, however, eight separate overloads for the Host method. Each of these overloads take in the application description, and either one or more address objects, as these are the only required parameters. You may also pass in an object to be used as a player context variable (we'll describe these shortly). You may also pass a member of the HostFlags enumeration. There is currently only one member of this enumeration, which allows DirectPlay to open a windows dialog to query for any missing addressing information.
We wrap our Host call into a try/catch block to allow for the case when the method fails for some reason. We could catch only exceptions derived from the DirectPlayExcetion class, but for this simple example, we'll simply catch them all. There are two methods we haven't seen before that will simply update the UI. We'll look at these now: private void AddText(string text) { label1.Text += (text + "\r\n"); } private void EnableSendDataButton(bool enable) { button3.Enabled = enable; } No need to go into these methods as they are quite self-explanatory. Running this application now and hitting the host button will start a DirectPlay peer-to-peer session, display a status message to this affect, and enable the send data button. With all that done, all we need now is another peer to connect to our session. Add the following clause to the end of the initialize method: else { try { connection.FindHosts(desc, null, deviceAddress, null, 0, 0, 0, FindHostsFlags.OkToQueryForAddressing); AddText("Looking for sessions."); } catch { AddText("Enumeration of sessions has failed."); } } Once again, we wrap our method in a try/catch block to be notified of any errors, as well as update our UI based on what we are doing. However, we aren't calling the Connect method; we are calling the FindHosts method. In some cases, it is possible to directly connect to an existing session; however, in most cases you will need to search for any existing hosts first. Much like the Host method, the FindHosts method takes in the application description, as well as the local device address. The second parameter is the host's address, which we don't happen to know right now, so we can just use null for this parameter. The fourth parameter for this method is any application-defined data you want to pass in to the server. The server can use this information in anyway it wants. The next three parameters control the behavior of how the hosts are enumerated. They control the number of times to send out the enumeration packets, how often it should wait before retrying another enumeration, and finally the time out value of the enumerations. By specifying zero for each of these parameters, the default values for the service provider will be used. The last parameter can be one or more members of the FindHostsFlags enumeration. The possible values of this enumeration are listed in Table 18.3.
If you try running the application now, you'll notice that clicking the connect button causes a dialog will show up asking for the remote machine's address. You can leave this blank to search the entire subnet of the network you are on. You can also specify the name or IP address of the machine you want to connect to. You'll notice that the FindHosts method returns no parameters, and currently there is no way to actually find out what hosts we've found. |