青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當(dāng)自強(qiáng)而不息

使用DirectPlay進(jìn)行網(wǎng)絡(luò)互聯(lián)(2)


本篇是使用DirectPlay進(jìn)行網(wǎng)絡(luò)互聯(lián)(1)的續(xù)篇。
 


使用地址

一個(gè)網(wǎng)絡(luò)使用IP地址和端口來(lái)傳送數(shù)據(jù),在DirectPlay中,使用DirectPlay專用對(duì)象IDirectPlay8Address來(lái)構(gòu)造地址。

The IDirectPlay8Address interface contains generic addressing methods used to create and manipulate addresses for Microsoft® DirectPlay® . This interface is one of the interfaces available through the CLSID_DirectPlay8Address COM object.

The IDirectPlay8Address interface contains the following methods.

IDirectPlay8Address Methods

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
BuildFromURLW
BuildFromURLA
Duplicate
SetEqual
IsEqual
Clear
GetURLW
GetURLA
GetSP
GetUserData
SetSP
SetUserData
GetNumComponents
GetComponentByName
GetComponentByIndex
AddComponent
GetDevice
SetDevice
BuildFromDPADDRESS
 

Remarks

In order to deliver messages, each participant in a multiplayer game must have a unique address. Addresses can refer either to the computer that your application is running on (device address), or a computer that your application needs to communicate with (host address).

DirectPlay represents addresses as URLs. These URLs are then encapsulated in the address object so that they can be passed to or from the DirectPlay API. In general, address URLs are strings that consist of three basic components in the following order: scheme, scheme separator, and data string.

All DirectPlay addresses use "x-directplay" as the scheme, and ":/" as the scheme separator. Using ":/" as a separator implies that the data that follows is opaque. In other words, the data string does not conform to any Internet standard, and should simply be passed on to the receiving application without modification. All DirectPlay URLs thus have the following general form:

x-directplay:/[data string]

There are two basic approaches to handling address objects:

  • Handle the data string directly, using normal string manipulation techniques.
  • Use the methods exposed by IDirectPlay8Address to obtain or modify the individual elements of the data string.

For more information on DirectPlay addresses, see DirectPlay Addressing.

常用的 IDirectPlay8Address方法有三個(gè):

IDirectPlay8Address::Clear 清除所有地址數(shù)據(jù)
IDirectPlay8Address::SetSP 設(shè)置服務(wù)提供者
IDirectPlay8Address::AddComponent 添加地址組件

使用地址對(duì)象之前,需要使用CoCreateInstance函數(shù)來(lái)創(chuàng)建它:
 
IDirectPlay8Server*         g_dp_server;    // DirectPlay Server

// create DirectPlay Server component

if(FAILED(CoCreateInstance(CLSID_DirectPlay8Server, NULL, CLSCTX_INPROC, IID_IDirectPlay8Server, (void**)&g_dp_server)))
    
return FALSE;


添加組件

一個(gè)地址對(duì)象只是包含Unicode文本字符串的簡(jiǎn)單對(duì)象,該文本字符串包含服務(wù)提供者、端口號(hào)以及其他可選信息,下圖顯示了可以添加到地址對(duì)象的組件以及每個(gè)組件的數(shù)據(jù)類型:

AddComponent函數(shù)的惟一用途就是創(chuàng)建該字符串以供其他對(duì)象使用。

Adds a component to the address. If the component is part of the address, it is replaced by the new value in this call.

Values are specified in native formats when making this call. Therefore, the lpvData parameter should be a recast pointer to a variable that holds the data in the native format. For example, if the component is a GUID, the lpvData parameter should be a recast pointer to a GUID.

This method validates that the predefined component types are the right format.

HRESULT AddComponent(
const WCHAR *const
pwszName,
const void *const lpvData,
const DWORD dwDataSize,
const DWORD dwDataType
);

Parameters

pwszName
[in] NULL-terminated Unicode string that contains the key for the component.
lpvData
[in] Pointer to a buffer that contains the value associated with the specified key. Data should be specified in its native format.
dwDataSize
[in] Size, in bytes, of the data in the buffer located at lpvData. The size depends on the data type. If the size is not specified correctly, the method returns DPNERR_INVALIDPARAM.
DWORD
Size = sizeof( DWORD )
GUID
Size = sizeof( GUID )
String
Size = size of the string in bytes, including NULL terminator.
dwDataType
[in] Data type of the value associated with this key. The data type can be one of the following:
DPNA_DATATYPE_STRING
Data is a NULL-terminated string.
DPNA_DATATYPE_DWORD
Data is a DWORD.
DPNA_DATATYPE_GUID
Data is a GUID.
DPNA_DATATYPE_BINARY
Data is in raw binary format.

Return Values

Returns S_OK if successful, or one of the following error values.

DPNERR_INVALIDPARAM
DPNERR_INVALIDPOINTER
DPNERR_NOTALLOWED

Remarks

See DirectPlay Addressing for a discussion of various address components and their keys.


設(shè)置服務(wù)提供者

下一步要做的就是選擇服務(wù)提供者,調(diào)用 IDirectPlay8Address::SetSP函數(shù)來(lái)設(shè)置。

Sets the service provider GUID in the address object. If a service provider is specified for this address, it is overwritten by this call.

HRESULT SetSP(
const GUID *const
pguidSP
);

Parameters

pguidSP
[in] Pointer to the service provider GUID.

Return Values

Returns S_OK if successful, or one of the following error values.

DPNERR_INVALIDPOINTER
DPNERR_NOTALLOWED
 


選擇端口

無(wú)論是主持一次會(huì)話(作為服務(wù)器端或單點(diǎn))還是使用客戶端網(wǎng)絡(luò)模型連接到一個(gè)遠(yuǎn)程系統(tǒng),接下來(lái)必須要做的就是選擇端口,如果要連接到遠(yuǎn)程系統(tǒng),就必須知道應(yīng)用程序所使用的端口,以便能夠連接到遠(yuǎn)程系統(tǒng)以及發(fā)送數(shù)據(jù)到遠(yuǎn)程系統(tǒng)。端口號(hào)可以隨意選擇,但是不要使用保留端口號(hào)(1 - 1024),選擇1024以上的端口號(hào)會(huì)比較安全??梢酝ㄟ^(guò)指定端口號(hào)0而讓DirectPlay來(lái)選擇一個(gè)端口號(hào),但是這樣做的弊病在于端口號(hào)可能為任意數(shù)字,就需要對(duì)端口號(hào)進(jìn)行查詢,推薦的做法是自己選擇一個(gè)端口號(hào)。

設(shè)置端口號(hào)使用 IDirectPlay8Address::AddComponent函數(shù)。

IDirectPlay8Address*    dp_address;

DWORD port = 21234;

// Set port
if(FAILED(dp_address->AddComponent(DPNA_KEY_PORT, &port, sizeof(DWORD), DPNA_DATATYPE_DWORD)))
{
      dp_address->Release();
      
return FALSE;
}
 


使用消息處理函數(shù)

消息處理回調(diào)函數(shù)非常簡(jiǎn)單,它僅僅需要區(qū)分接收到的是哪一種消息,并盡可能快地處理消息,可以將消息處理函數(shù)想象成一個(gè)漏斗,如下圖所示:

以下是一個(gè)簡(jiǎn)單的消息處理函數(shù)代碼實(shí)例:

//----------------------------------------------------------------------------------------
// Callback function that receives all messages from the client, and receives indications 
// of session changes from the IDirectPlay8Client interface. 
//----------------------------------------------------------------------------------------
HRESULT WINAPI Net_Msg_Handle(PVOID user_context, DWORD message_id, PVOID msg_buffer)
{
    DPNMSG_CREATE_PLAYER*   create_player;  
// contains information for the DPN_MSGID_CREATE_PLAYER system message
    DPNMSG_DESTROY_PLAYER*  destroy_player; // contains information for the DPN_MSGID_DESTROY_PLAYER system message

    
switch(message_id)
    {
    
// Microsoft DirectPlay generates the DPN_MSGID_CREATE_PLAYER message when a player is added to a 
    // peer-to-peer or client/server session.
    case DPN_MSGID_CREATE_PLAYER:
        create_player = (DPNMSG_CREATE_PLAYER*) msg_buffer
        
        
// 處理創(chuàng)建玩家
        
        
return S_OK;

    
// Microsoft DirectPlay generates the DPN_MSGID_DESTROY_PLAYER message when a player leaves a peer-to-peer 
    // or client/server session.
    case DPN_MSGID_DESTROY_PLAYER:
        destroy_player = (DPNMSG_DESTROY_PLAYER *) msg_buffer;

        
// 處理銷(xiāo)毀玩家
        
        
return S_OK;       
    }

    
return S_FAIL;
}

通過(guò)switch-case語(yǔ)句,可以快速找到要處理的消息,而略過(guò)其他消息。如果處理消息成功,就返回S_OK,否則返回E_FAIL表示處理失敗。每個(gè)消息都帶有一個(gè)數(shù)據(jù)緩沖區(qū),這些緩沖區(qū)被類型轉(zhuǎn)換為適當(dāng)?shù)慕Y(jié)構(gòu)體,除了它們是以DPNMSG_而不是DPN_MSGID_開(kāi)頭之外,這些結(jié)構(gòu)體和消息宏幾乎具有相同的命名規(guī)則。
 


配置會(huì)話信息

每一個(gè)網(wǎng)絡(luò)對(duì)象都需要知道一些要主持或要加入的會(huì)話信息,這些信息包含在一個(gè)結(jié)構(gòu)體中:

Describes the settings for a Microsoft® DirectPlay® application.

typedef struct _DPN_APPLICATION_DESC{
DWORD dwSize;
DWORD dwFlags;
GUID guidInstance;
GUID guidApplication;
DWORD dwMaxPlayers;
DWORD dwCurrentPlayers;
WCHAR* pwszSessionName;
WCHAR* pwszPassword;
PVOID pvReservedData;
DWORD dwReservedDataSize;
PVOID pvApplicationReservedData;
DWORD dwApplicationReservedDataSize;
} DPN_APPLICATION_DESC, *PDPN_APPLICATION_DESC;

Members

dwSize
Size of the DPN_APPLICATION_DESC structure. The application must set this member before it uses the structure.
dwFlags
One of the following flags describing application behavior.
DPNSESSION_CLIENT_SERVER
This type of session is client/server. This flag cannot be combined with DPNSESSION_MIGRATE_HOST.
DPNSESSION_MIGRATE_HOST
Used in peer-to-peer sessions, enables host migration. This flag cannot be combined with DPNSESSION_CLIENT_SERVER.
DPNSESSION_NODPNSVR
Do not forward enumerations to your host from DPNSVR. See Using the DirectPlay DPNSVR Application for details.
DPNSESSION_REQUIREPASSWORD
The session is password protected. If this flag is set, pwszPassword must be a valid string.
guidInstance
Globally unique identifier (GUID) that is generated by DirectPlay at startup, representing the instance of this application. This member is an [out] parameter when calling the GetApplicationDesc method exposed by the IDirectPlay8Peer, IDirectPlay8Client, and IDirectPlay8Server interfaces. It is an optional [in] parameter when calling the Connect method exposed by the IDirectPlay8Peer and IDirectPlay8Client interfaces. It must be set to GUID NULL when you call the SetApplicationDesc method exposed by the IDirectPlay8Server and IDirectPlay8Peer interfaces. You cannot obtain this GUID by calling the IDirectPlay8Server::Host or IDirectPlay8Peer::Host methods. You must obtain the GUID by calling a GetApplicationDesc method.
guidApplication
Application GUID.
dwMaxPlayers
Variable of type DWORD, specifying the maximum number of players allowed in the session. Set this member to 0 to specify an unlimited number of players.
dwCurrentPlayers
Variable of type DWORD specifying the number of players currently connected to the session. This member is an [out] parameter that is set only by the GetApplicationDescription method exposed by IDirectPlay8Peer, IDirectPlay8Client, and IDirectPlay8Server.
pwszSessionName
Pointer to a variable of type WCHAR specifying the Unicode name of the session. This member is set by the host or server only for informational purposes. A client cannot use this name to connect to a host or server.
pwszPassword
Pointer to a variable of type WCHAR specifying the Unicode password that is required to connect to the session. This must be NULL if the DPNSESSION_REQUIREPASSWORD is not set in the dwFlags member.
pvReservedData
Pointer to DirectPlay reserved data. An application should never modify this value.
dwReservedDataSize
Variable of type DWORD specifying the size of data contained in the pvReservedData member. An application should never modify this value.
pvApplicationReservedData
Pointer to application-specific reserved data. This value is optional and may be set to NULL.
dwApplicationReservedDataSize
Variable of type DWORD specifying the size of the data in the pvApplicationReservedData member. This value is optional and may be set to 0.

Remarks

Multiple instances of the application can run simultaneously. "Application" refers to a specific instance of an application.

The dwMaxPlayers, pvApplicationReservedData, dwApplicationReservedDataSize, pwszPassword, and pwszSessionName members can be set when calling the Host or SetApplicationDesc methods exposed by the IDirectPlay8Server and IDirectPlay8Peer interfaces.

When connecting to a password protected session, the data in the pwszPassword member is transmitted in clear text to the host.


會(huì)話數(shù)據(jù)

一個(gè)服務(wù)器端需要配置允許的最大玩家數(shù)(如果需要進(jìn)行限制)、會(huì)話名稱和登陸密碼、會(huì)話標(biāo)志以及應(yīng)用程序GUID,如果不想限制最大玩家數(shù),將dwMaxPlayers字段設(shè)置為0即可。
 
// application GUID
GUID g_app_guid = { 0xababbe60, 0x1ac0, 0x11d5, { 0x90, 0x89, 0x44, 0x45, 0x53, 0x54, 0x0, 0x1 } };

DPN_APPLICATION_DESC app_desc;  
// Describes the settings for a Microsoft DirectPlay application

// Setup the application description structure

ZeroMemory(&app_desc, 
sizeof(DPN_APPLICATION_DESC));

app_desc.dwSize          = 
sizeof(DPN_APPLICATION_DESC);
app_desc.dwFlags         = DPNSESSION_CLIENT_SERVER;
app_desc.guidApplication = g_app_guid;
app_desc.pwszSessionName = L"SercverSession";
app_desc.dwMaxPlayers    = 256;

客戶端結(jié)構(gòu)體所需設(shè)置的信息包括要加入的會(huì)話名稱和密碼、客戶端 / 服務(wù)器端會(huì)話標(biāo)志以及應(yīng)用程序GUID。一定要使用和服務(wù)器端相同的應(yīng)用程序GUID,這樣客戶端和服務(wù)器端才能在網(wǎng)絡(luò)中找到對(duì)方。



服務(wù)器端的處理

獲得網(wǎng)絡(luò)的第一步是創(chuàng)建一個(gè)服務(wù)器端。服務(wù)器端扮演了網(wǎng)絡(luò)游戲的中央處理單元,所有玩家通過(guò)客戶端應(yīng)用程序連接到服務(wù)器端并在二者之間來(lái)回傳輸數(shù)據(jù)。服務(wù)器端保持游戲數(shù)據(jù)同步并告知玩家當(dāng)前的游戲狀態(tài),雖然對(duì)于小型網(wǎng)絡(luò)游戲而言,這并不是最快的辦法,但對(duì)于大型網(wǎng)絡(luò)游戲而言,則是最好的方法。

要?jiǎng)?chuàng)建服務(wù)器端,需要調(diào)用IDirectPlay8Server::Host來(lái)主持會(huì)話。

Creates a new client/server session, hosted by the local computer.

HRESULT Host(
const DPN_APPLICATION_DESC *const
pdnAppDesc,
IDirectPlay8Address **const prgpDeviceInfo,
const DWORD cDeviceInfo,
const DPN_SECURITY_DESC *const pdpSecurity,
const DPN_SECURITY_CREDENTIALS *const pdpCredentials,
VOID *const pvPlayerContext,
const DWORD dwFlags
);

Parameters

pdnAppDesc
[in] Pointer to a DPN_APPLICATION_DESC structure that describes the application.
prgpDeviceInfo
[in] Pointer to an array of IDirectPlay8Address objects containing device addresses that should be used to host the application.
cDeviceInfo
[in] Variable of type DWORD that specifies the number of device address objects in the array pointed to by prgpDeviceInfo.
pdpSecurity
[in] Reserved. Must be set to NULL.
pdpCredentials
[in] Reserved. Must be set to NULL.
pvPlayerContext
[in] Pointer to the context value of the player. This value is preset when the local computer handles the DPN_MSGID_CREATE_PLAYER message. This parameter is optional, and may be set to NULL.
dwFlags
[in] The following flag can be specified.
DPNHOST_OKTOQUERYFORADDRESSING
Setting this flag will display a standard Microsoft® DirectPlay® dialog box, which queries the user for more information if not enough information is passed in this method.

Return Values

Returns S_OK if successful, or the following error value.

DPNERR_DATATOOLARGE
DPNERR_INVALIDPARAM

Remarks

If you set the DPNHOST_OKTOQUERYFORADDRESSING flag in dwFlags, the service provider may attempt to display a dialog box to ask the user to complete the address information. You must have a visible window present when the service provider tries to display the dialog box, or your application will lock.

The maximum size of the application data that you assign to the pvApplicationReservedData member of the DPN_APPLICATION_DESC structure is limited by the service provider's Maximum Transmission Unit. If your application data is too large, the method will fail and return DPNERR_DATATOOLARGE.


以下是創(chuàng)建服務(wù)器端會(huì)話的代碼示例:
 
HWND g_hwnd;

// application GUID
GUID g_app_guid = { 0xababbe60, 0x1ac0, 0x11d5, { 0x90, 0x89, 0x44, 0x45, 0x53, 0x54, 0x0, 0x1 } };

IDirectPlay8Server*         g_dp_server;    
// DirectPlay Server

BOOL g_is_hosting;              
// flag indicates whether host started or not

//--------------------------------------------------------------------------------
// Start hosting a server which GUID specified by adapter_guid.
//--------------------------------------------------------------------------------
BOOL Start_Session(GUID* adapter_guid)
{
    
// Make sure there's an adapter
    if(adapter_guid == NULL)
        
return FALSE;

    
// Need to re-assign a network handler as quitting a previous session to clears it.
    // Close the connection first before assigning a new network handler.
    //
    // Closes the open connnection to a session.
    g_dp_server->Close(0);

    
// Initialize DirectPlay Server
    if(FAILED(g_dp_server->Initialize(NULL, Net_Msg_Handle, 0)))
        
return FALSE;

    IDirectPlay8Address*    dp_address;

    
// Create an address object and fill it with information
    if(FAILED(CoCreateInstance(CLSID_DirectPlay8Address, NULL, CLSCTX_INPROC, IID_IDirectPlay8Address, (void**)&dp_address)))
        
return FALSE;

    
// Set the protocol to TCP/IP
    //
    // Sets the service provider GUID in the address object.
    // If a service provider is specified for this address, it is overwrittern by this call.
    if(FAILED(dp_address->SetSP(&CLSID_DP8SP_TCPIP)))
    {
        dp_address->Release();
        
return FALSE;
    }

    
// Set the port
    DWORD port = 21234;

    
// Adds a component to the address.
    // If the component is part of the address, it is replaced by the new value in this call.

    // Set port
    if(FAILED(dp_address->AddComponent(DPNA_KEY_PORT, &port, sizeof(DWORD), DPNA_DATATYPE_DWORD)))
    {
        dp_address->Release();
        
return FALSE;
    }

    
// Set the adapter
    if(FAILED(dp_address->AddComponent(DPNA_KEY_DEVICE, adapter_guid, sizeof(GUID), DPNA_DATATYPE_GUID)))
    {
        dp_address->Release();
        
return FALSE;
    }

    DPN_APPLICATION_DESC app_desc;  
// Describes the settings for a Microsoft DirectPlay application

    // Setup the application description structure

    ZeroMemory(&app_desc, 
sizeof(DPN_APPLICATION_DESC));

    app_desc.dwSize          = 
sizeof(DPN_APPLICATION_DESC);
    app_desc.dwFlags         = DPNSESSION_CLIENT_SERVER;
    app_desc.guidApplication = g_app_guid;
    app_desc.pwszSessionName = L"SercverSession";
    app_desc.dwMaxPlayers    = 256;

    
// Start hosting
    //
    // Creates a new client/server session, hosted by the local computer.
    if(FAILED(g_dp_server->Host(&app_desc, &dp_address, 1, NULL, NULL, NULL, 0)))
    {
        dp_address->Release();
        
return FALSE;
    }

    
// Release the address component
    dp_address->Release();

    
// Disables combo-box control.
    //
    // Enables or disables mouse and keyboard input to the specified window or control. 
    // When input is disabled, the window does not receive input such as mouse clicks and key presses. 
    // When input is enabled, the window receives all input. 
    EnableWindow(GetDlgItem(g_hwnd, IDC_ADAPTERS), FALSE);

    
// Setup the dialog information
    SetWindowText(GetDlgItem(g_hwnd, IDC_STARTSTOP), "Stop");

    g_is_hosting = TRUE;

    
return TRUE;
}

處理玩家

服務(wù)器端創(chuàng)建好之后,接收到的第一個(gè)消息就是創(chuàng)建一個(gè)玩家。創(chuàng)建的第一個(gè)玩家總是主機(jī)玩家,然后其他玩家才開(kāi)始被創(chuàng)建和釋放,但是在整個(gè)會(huì)話過(guò)程中,主機(jī)玩家始終都存在。創(chuàng)建玩家消息通過(guò)DPN_MSGID_CREATE_PLAYER定義,并且消息緩沖區(qū)被類型轉(zhuǎn)換成 DPNMSG_CREATE_PLAYER結(jié)構(gòu)體。

Microsoft® DirectPlay® generates the DPN_MSGID_CREATE_PLAYER message when a player is added to a peer-to-peer or client/server session.

The DPNMSG_CREATE_PLAYER structure contains information for the DPN_MSGID_CREATE_PLAYER system message.

typedef struct _DPNMSG_CREATE_PLAYER{
DWORD dwSize;
DPNID dpnidPlayer;
PVOID pvPlayerContext;
} DPNMSG_CREATE_PLAYER, *PDPNMSG_CREATE_PLAYER;
dwSize
Size of this structure.
dpnidPlayer
DPNID of the player that was added to the session.
pvPlayerContext
Player context value.

Return Values

Return DPN_OK.

Remarks

The only method of setting the player context value is through this system message. You can either set the player context value directly, through this message, or indirectly through DPN_MSGID_INDICATE_CONNECT. Once a player context value has been set, it cannot be changed.


玩家相關(guān)數(shù)據(jù)指針pvPlayerContext是用來(lái)在應(yīng)用程序中定義玩家的信息,該數(shù)據(jù)指針可以指向一個(gè)結(jié)構(gòu)體、類實(shí)例或包含了玩家名稱、健康狀態(tài)、年齡、當(dāng)前武器以及護(hù)甲等的數(shù)據(jù)緩沖區(qū)。通過(guò)把玩家相關(guān)數(shù)據(jù)指針傳遞給DirectPlay,它就能帶來(lái)更快的訪問(wèn)速度。因?yàn)闀r(shí)間關(guān)系,必須很快遍歷一個(gè)已登錄玩家的列表來(lái)查找一個(gè)匹配的玩家ID時(shí),這樣做就能節(jié)省時(shí)間。

一個(gè)玩家有一個(gè)與之關(guān)聯(lián)的名稱,而且要能夠取回玩家名稱以便在游戲中使用(因?yàn)闆](méi)有人想使用一個(gè)數(shù)字作為其名稱),這就是IDirectPlay8Server:: GetClientInfo函數(shù)所實(shí)現(xiàn)的功能。

Retrieves the client information set for the specified client.

HRESULT GetClientInfo(
const DPNID
dpnid,
DPN_PLAYER_INFO *const pdpnPlayerInfo,
DWORD *const pdwSize,
const DWORD dwFlags
);

Parameters

dpnid
[in] Variable of type DPNID that specifies the identifier of the client to retrieve the information for.
pdpnPlayerInfo
[out] Pointer to a DPN_PLAYER_INFO structure that is filled with client information. If pdwSize is not set to NULL, you must set pdpnPlayerInfo.dwSize to an appropriate value.
pdwSize
[in,out] Pointer to a variable of type DWORD that contains the size of the client data, in bytes, returned in the pdpnPlayerInfo parameter. If the buffer is too small, this method returns DPNERR_BUFFERTOOSMALL and this parameter contains the size of the required buffer.
dwFlags
[in] Flags describing the information returned for the client. Currently, both of the following flags are returned.
DPNINFO_NAME
The DPN_PLAYER_INFO structure contains the name set for the client.
DPNINFO_DATA
The DPN_PLAYER_INFO structure contains the data set for the client.

Return Values

Returns S_OK if successful, or one of the following error values.

DPNERR_BUFFERTOOSMALL
DPNERR_INVALIDPARAM
DPNERR_INVALIDPLAYER

Remarks

Call this method after the server receives a DPN_MSGID_CLIENT_INFO message from the application. This message indicates that a client has updated its information.

Microsoft® DirectPlay® returns the DPN_PLAYER_INFO structure, and the pointers assigned to the structure's pwszName and pvData members in a contiguous buffer. If the two pointers were set, you must have allocated enough memory for the structure, plus the two pointers. The most robust way to use this method is to first call it with pdwSize set to NULL. When the method returns, pdwSize will point to the correct value. Use that value to allocate memory for the structure and call the method a second time to retrieve the information.

When the method returns, the dwInfoFlags member of the DPN_PLAYER_INFO structure will always have the DPNINFO_DATA and DPNINFO_NAME flags set, even if the corresponding pointers are set to NULL. These flags are used when calling IDirectPlay8Client::SetClientInfo, to notify DirectPlay of which values have changed.

Transmission of nonstatic information should be handled with the IDirectPlay8Client::Send method because of the high cost of using the IDirectPlay8Client::SetPeerInfo method.

The player sets the information by calling IDirectPlay8Client::SetClientInfo.

pdpnPlayerInfo指向玩家信息結(jié)構(gòu)體

Describes static player information.

typedef struct _DPN_PLAYER_INFO{
DWORD dwSize;
DWORD dwInfoFlags;
PWSTR pwszName;
PVOID pvData;
DWORD dwDataSize;
DWORD dwPlayerFlags;
} DPN_PLAYER_INFO, *PDPN_PLAYER_INFO;

Members

dwSize
Variable of type DWORD describing the size of this structure.
dwInfoFlags
Variable of type DWORD containing flags that specify the type of information contained in this structure. When a GetPlayerInfo method returns, the dwInfoFlags member of the DPN_PLAYER_INFO will always have both flags set, even if the corresponding pointers are set to NULL. These flags are used when calling IDirectPlay8Peer::SetPeerInfo, to notify Microsoft® DirectPlay® which values have changed.
DPNINFO_NAME
The pwszName member contains valid data.
DPNINFO_DATA
The pvData member contains valid data.
pwszName
Pointer to a variable of type PWSTR specifying the Unicode name of the player.
pvData
Pointer to the data describing the player.
dwDataSize
Variable of type DWORD that specifies the size of the data contained in the pvData member.
dwPlayerFlags
Variable of type DWORD that may contain one of the following flags.
DPNPLAYER_LOCAL
This information is for the local player.
DPNPLAYER_HOST
This player is the host for the application.

Remarks

When using this structure in the IDirectPlay8Peer::GetPeerInfo and IDirectPlay8Server::GetClientInfo methods, dwInfoFlags must be set to 0.

When using this structure in the IDirectPlay8Client::SetClientInfo, IDirectPlay8Peer::SetPeerInfo, or IDirectPlay8Server::SetServerInfo methods, dwPlayerFlags should be set to zero.

 

以下是處理創(chuàng)建玩家的代碼實(shí)例:

// application variables
struct PLAYER_INFO
{
    DPNID   player_id;  
// DirectPlay Player ID
    char    name[26];   // Player Name

    PLAYER_INFO()   { player_id = 0; }
};

// window handles, class.
HWND g_hwnd;
char g_class_name[] = "ServerClass";

// application GUID
GUID g_app_guid = { 0xababbe60, 0x1ac0, 0x11d5, { 0x90, 0x89, 0x44, 0x45, 0x53, 0x54, 0x0, 0x1 } };

IDirectPlay8Server*         g_dp_server;    
// DirectPlay Server
DPN_SERVICE_PROVIDER_INFO*  g_adapter_list; // adapters
DWORD                       g_num_adapters; // number of adapters

PLAYER_INFO g_player_info[256]; 
// player information
BOOL g_is_hosting;              // flag indicates whether host started or not

//----------------------------------------------------------------------------------------
// Callback function that receives all messages from the client, and receives indications 
// of session changes from the IDirectPlay8Client interface. 
//----------------------------------------------------------------------------------------
HRESULT WINAPI Net_Msg_Handle(PVOID user_context, DWORD message_id, PVOID msg_buffer)
{
    DPNMSG_CREATE_PLAYER*   create_player;  
// contains information for the DPN_MSGID_CREATE_PLAYER system message
    DPNMSG_DESTROY_PLAYER*  destroy_player; // contains information for the DPN_MSGID_DESTROY_PLAYER system message
    DPNMSG_RECEIVE*         receive_data;   // contains information for the DPN_MSGID_RECEIVE system message
    DPN_PLAYER_INFO*        dpn_player_info;// describes static player informaion
    DPN_BUFFER_DESC         buffer_desc;    // used dy DirectPlay for generic buffer information

    DPNHANDLE       async_handle;
    PLAYER_INFO*    player_info;
    
int             index;
    DWORD           size;
    
char            message[512];
    HRESULT         rv;

    
switch(message_id)
    {
    
// Microsoft DirectPlay generates the DPN_MSGID_CREATE_PLAYER message when a player is added to a 
    // peer-to-peer or client/server session.
    case DPN_MSGID_CREATE_PLAYER:
        create_player = (DPNMSG_CREATE_PLAYER*) msg_buffer;

        
// get player name and save it

        size = 0;
        dpn_player_info = NULL;

        
// Retrieves the client information set for the specified client
        rv = g_dp_server->GetClientInfo(create_player->dpnidPlayer, dpn_player_info, &size, 0);

        
if(FAILED(rv) && rv != DPNERR_BUFFERTOOSMALL)
        {
            
// skip this if this is a host player
            if(rv == DPNERR_INVALIDPLAYER)
                
break;

            
return E_FAIL;
        }

        
if((dpn_player_info = (DPN_PLAYER_INFO*) new BYTE[size]) == NULL)
            
return E_FAIL;

        ZeroMemory(dpn_player_info, size);
        dpn_player_info->dwSize = 
sizeof(DPN_PLAYER_INFO);

        
// retrieves the client information set again
        if(FAILED(g_dp_server->GetClientInfo(create_player->dpnidPlayer, dpn_player_info, &size, 0)))
        {
            delete[] dpn_player_info;
            
return E_FAIL;
        }

        
// Find an empty player structure to use

        index = -1;

        
for(int i = 0; i < 256; i++)
        {
            
if(g_player_info[i].player_id == 0)
            {
                index = i;
                
break;
            }
        }

        
if(index == -1)
        {
            delete[] dpn_player_info;
            
return E_FAIL;
        }

        
// set player context pointer
        create_player->pvPlayerContext = (void*) &g_player_info[index];

        
// save player ID
        g_player_info[index].player_id = create_player->dpnidPlayer;
        
        wcstombs(g_player_info[index].name, dpn_player_info->pwszName, 256);
        
        
// add player to list
        SendMessage(GetDlgItem(g_hwnd, IDC_USERS), LB_ADDSTRING, 0, (LPARAM) g_player_info[index].name);

        
// send a message to all players notifying someone joined
        sprintf(message, "%s joined!", g_player_info[index].name);
        Send_Text_Msg(DPNID_ALL_PLAYERS_GROUP, message);

        delete[] dpn_player_info;

        
break;
    }

    
// return S_OK to signify the message was handled OK.
    return S_OK;
}

posted on 2007-08-13 19:11 lovedday 閱讀(811) 評(píng)論(0)  編輯 收藏 引用

公告

導(dǎo)航

統(tǒng)計(jì)

常用鏈接

隨筆分類(178)

3D游戲編程相關(guān)鏈接

搜索

最新評(píng)論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美视频一区二区三区…| 亚洲国产天堂久久综合| 亚洲国产欧美一区二区三区久久 | 亚洲国内在线| 亚洲女同同性videoxma| 亚洲一区二区三区激情| 久久久久久久性| 国产精品福利在线观看| 99re66热这里只有精品4| 亚洲日本精品国产第一区| 久久综合九色综合欧美狠狠| 久久亚洲国产成人| 精东粉嫩av免费一区二区三区| 亚洲永久在线观看| 香港久久久电影| 国产精品久久一级| 亚洲一二三四区| 午夜亚洲视频| 国产日韩一区在线| 小黄鸭精品aⅴ导航网站入口 | 欧美一区二区三区四区视频| 欧美性猛交99久久久久99按摩 | 亚洲字幕在线观看| 国产精品高潮呻吟久久| 这里只有精品电影| 午夜在线电影亚洲一区| 国产亚洲激情| 狂野欧美一区| 亚洲激情在线| 亚洲影院免费| 国产欧美日韩不卡| 久久精品欧美日韩精品| 欧美高清在线一区| 日韩视频在线免费| 国产精品国产a| 欧美一区在线视频| 欧美国产91| 亚洲桃花岛网站| 国产日韩一区| 鲁大师影院一区二区三区| 亚洲精品影视| 欧美一区二区三区四区在线| 在线电影欧美日韩一区二区私密| 欧美成人免费在线| 中文精品视频| 老司机成人网| 亚洲一区二区高清视频| 国内久久视频| 欧美日韩国产精品成人| 亚洲欧美综合另类中字| 亚洲高清视频在线| 欧美亚洲一区在线| 亚洲激情视频在线观看| 国产精品高潮呻吟久久av黑人| 亚洲一区二区三区视频播放| 蜜臀av在线播放一区二区三区 | 一区二区三区四区五区精品视频| 国产伦精品一区二区三区视频孕妇| 久久人人爽人人| 亚洲网友自拍| 亚洲国产91精品在线观看| 欧美一区二区高清在线观看| 亚洲精品欧美极品| 国产亚洲精品v| 欧美亚韩一区| 免费在线观看日韩欧美| 亚洲欧美日韩国产中文在线| 亚洲国产欧美日韩另类综合| 久久精品一区| 亚洲欧美在线播放| 亚洲精品久久久久| 一区福利视频| 国产精品自拍网站| 欧美日韩午夜在线视频| 久久综合九九| 欧美伊人久久久久久午夜久久久久| 亚洲精品免费看| 欧美成人高清视频| 久久久综合免费视频| 亚洲欧美另类国产| 99国产精品视频免费观看一公开| 精品成人a区在线观看| 国产女人18毛片水18精品| 欧美日韩精品免费观看视一区二区 | 久久欧美中文字幕| 欧美一区二区高清在线观看| 日韩一级大片在线| 亚洲国产精品va| 欧美成人蜜桃| 麻豆国产va免费精品高清在线| 欧美一区二区视频网站| 亚洲香蕉网站| 在线亚洲电影| 亚洲午夜伦理| 国产精品99久久久久久久vr| 日韩香蕉视频| 99在线|亚洲一区二区| 亚洲黄色影院| 亚洲国产一区二区a毛片| 狠狠色狠狠色综合日日小说| 国产一区二区精品久久| 国产日本欧美一区二区| 国产美女诱惑一区二区| 国产日韩欧美一区| 国产欧美一区二区三区另类精品| 国产精品系列在线播放| 国产日本欧美一区二区三区在线| 国产伦精品一区二区三区高清版| 国产精品一二三四| 国产伦精品一区二区三区免费| 国产精品羞羞答答| 国产一区在线播放| 亚洲电影专区| 亚洲毛片网站| 亚洲午夜国产一区99re久久| 亚洲一区精品在线| 久久激情五月丁香伊人| 久久综合九色综合久99| 欧美黄色一区二区| 亚洲精品国产精品国自产观看浪潮 | 久久久精品性| 欧美大片免费| 亚洲精品日韩在线| 亚洲一区二区三区在线视频| 欧美亚洲免费电影| 蜜桃av久久久亚洲精品| 欧美日韩国产精品一区| 国产精品美女久久福利网站| 国产亚洲欧美一级| 亚洲黄色在线看| 亚洲一区在线视频| 久久久久国产精品www| 欧美黄免费看| 亚洲一区二区成人| 久久亚洲国产精品日日av夜夜| 欧美区高清在线| 国产欧美精品一区二区三区介绍| 亚洲大胆人体在线| 亚洲一区一卡| 美日韩精品免费| 一区二区三区欧美成人| 久久亚洲精品一区| 国产精品高潮呻吟| 亚洲激情网址| 欧美在线免费观看亚洲| 亚洲第一中文字幕| 亚洲欧美日韩国产成人精品影院| 麻豆av一区二区三区久久| 国产精品国产| 亚洲精选成人| 久久久噜噜噜| 中文日韩在线| 免费观看一区| 国产婷婷精品| 亚洲一区二区在线免费观看| 免费观看成人| 欧美一区二区三区在线| 欧美日韩 国产精品| 尤物九九久久国产精品的特点| 亚洲视频电影图片偷拍一区| 欧美v国产在线一区二区三区| 夜夜爽www精品| 欧美成在线视频| 今天的高清视频免费播放成人 | 在线观看不卡av| 欧美一区二区三区四区高清| 亚洲精品视频在线观看网站| 久久亚洲精品视频| 国外成人免费视频| 欧美在线免费播放| 亚洲淫性视频| 欧美色综合网| 亚洲午夜未删减在线观看| 亚洲国产精品成人综合| 久久亚洲综合色| 经典三级久久| 久久理论片午夜琪琪电影网| 亚洲欧美日韩国产成人精品影院| 欧美日韩一级黄| 夜夜爽夜夜爽精品视频| 亚洲人成在线播放| 欧美福利视频网站| 亚洲激情网址| 亚洲黄网站在线观看| 免费观看在线综合| 亚洲精品国产系列| 亚洲国产黄色片| 欧美大片免费| 9久草视频在线视频精品| 亚洲国产小视频在线观看| 欧美激情影音先锋| 99re热这里只有精品视频| 亚洲经典自拍| 欧美日韩三区四区| 亚洲系列中文字幕| 亚洲桃花岛网站| 国产女主播一区二区| 欧美影片第一页| 欧美专区在线| 亚洲国产视频一区|