Microsoft DirectX 9.0 SDK Update (Summer 2003) |
hr = pDP8Client->EnumHosts(&dpnad, pDP8AddressHost, pDP8AddressDevice, NULL, 0, INFINITE, 0, 0, NULL, &dpnhEnumHosts, 0);
Microsoft® DirectPlay® will automatically cancel all outstanding IDirectPlay8Client::EnumHosts operations for you when the connect operation completes successfully. If the connect fails, the enumerations will continue running. You can then cancel them using the IDirectPlay8Client::CancelAsyncOperation method.
To ensure that the connect operation uses the same virtual connection as the enumeration, the host and device address objects specified to IDirectPlay8Client::Connect should be the same as those included in the corresponding DPN_MSGID_ENUM_HOSTS_RESPONSE message. For examples of how to add a reference or duplicate these addresses, see the DirectPlay C++ Samples.
The application sends enumeration queries to the DPNSVR port when the DPNA_KEY_PORT component is not specified in the IDirectPlay8Address host object passed to IDirectPlay8Client::EnumHosts. However the hosts reply from their respective game ports. Some NAT devices expect replies to come from the port to which the client originally sent, and might therefore drop the enumeration response. If your application uses DPNSVR to help with session discovery, it should also attempt to enumerate the game port directly.
The host can retrieve its addresses using IDirectPlay8Server::GetLocalHostAddresses and pass it in string format to the client using IDirectPlay8Address::GetURLA through a match-making service. The client can then convert the string back into an address using the IDirectPlay8Address::BuildFromURLA method as shown in the following example.
IDirectPlay8Address *pDP8AddressHost = NULL; hr = CoCreateInstance(CLSID_DirectPlay8Address, CLSCTX_INPROC_SERVER, IID_IDirectPlay8Address, NULL, (PVOID*) (&pDP8AddressHost)); hr = pDP8AddressHost->BuildFromURLA(szHostAddress);
This address object can then be passed to IDirectPlay8Client::EnumHosts or IDirectPlay8Client::Connect.
Applications should almost always let DirectPlay choose the local port or ports when enumerating or connecting. However, you might want to allow the user to select a local port. This can be added to a device address using the DPNA_KEY_PORT component as shown in the following example.
DWORD dwUserSelectedPort; // value retrieved from user input if (dwUserSelectedPort != 0) { // User specified a port value; use it. hr = pDP8AddressDevice->AddComponent(DPNA_KEY_PORT, &dwUserSelectedPort, sizeof(dwUserSelectedPort), DPNA_DATATYPE_DWORD); } else { // Let DirectPlay select; don't add port component. }
This address object is then passed to IDirectPlay8Client::EnumHosts or IDirectPlay8Client::Connect for the device address parameter.
When the client has Microsoft Windows® Internet Connection Firewall enabled or is behind a Universal Plug and Play (UPnP) NAT device, DirectPlay will attempt to enable port forwarding for your application automatically. This asks the device to accept all packets received from the Internet on a particular port and forward them to a particular address and port inside the private network. In many cases, this is unnecessary, particularly when the server is known to be on the open Internet. You can decrease the time required by IDirectPlay8Client::EnumHosts or IDirectPlay8Client::Connect and prevent automated traversal by setting the DPNA_KEY_TRAVERSALMODE component to DPNA_TRAVERSALMODE_NONE as shown in the following example.
DWORD dwTraversalMode = DPNA_TRAVERSALMODE_NONE; hr = pDP8AddressDevice->AddComponent(DPNA_KEY_TRAVERSALMODE, &dwTraversalMode, sizeof(dwTraversalMode), DPNA_DATATYPE_DWORD);