대화 관리
클라이언트와 서버 간의 대화는 항상 클라이언트의 요청에 따라 설정됩니다. 대화가 설정되면 각 파트너는 대화를 식별하는 핸들을 받습니다. 파트너는 다른 DDEML(동적 데이터 교환 관리 라이브러리) 함수에서 이 핸들을 사용하여 트랜잭션을 보내고 대화를 관리합니다. 클라이언트는 단일 서버와의 대화를 요청하거나 하나 이상의 서버와 여러 대화를 요청할 수 있습니다.
다음 항목에서는 애플리케이션이 새 대화를 설정하고 기존 대화에 대한 정보를 가져오는 방법을 설명합니다.
단일 대화
클라이언트 애플리케이션은 DdeConnect 함수를 호출하고 서버 애플리케이션의 서비스 이름과 대화의 토픽 이름을 포함하는 문자열을 식별하는 문자열 핸들을 지정하여 서버와의 단일 대화를 요청합니다. DDEML은 DdeConnect 지정된 것과 일치하는 서비스 이름을 등록했거나 DdeNameService호출하여 서비스 이름 필터링을 해제한 각 서버 애플리케이션의 DDE(동적 데이터 교환) 콜백 함수에 XTYP_CONNECT 트랜잭션을 전송하여 응답합니다. 서버는 DdeInitialize 함수에서 CBF_FAIL_CONNECTIONS 필터 플래그를 지정하여 XTYP_CONNECT 트랜잭션을 필터링할 수도 있습니다. XTYP_CONNECT 트랜잭션 중에 DDEML은 서비스 이름과 토픽 이름을 서버에 전달합니다. 서버는 이름을 검사하고 서비스 이름 및 토픽 이름 쌍을 지원하는 경우 TRUE 반환하거나 그렇지 않은 경우 FALSE 반환해야 합니다.
클라이언트의 연결 요청에 긍정적으로 응답하는 서버가 없는 경우 클라이언트는 DdeConnectNULL 받고 대화가 설정되지 않습니다. 서버가 TRUE 반환하는 경우 대화가 설정되고 클라이언트가 대화 핸들을 받습니다( 대화를 식별하는 DWORD 값). 클라이언트는 후속 DDEML 호출에서 핸들을 사용하여 서버에서 데이터를 가져옵니다. 서버가 CBF_SKIP_CONNECT_CONFIRMS 필터 플래그를 지정하지 않는 한 서버는 XTYP_CONNECT_CONFIRM 트랜잭션을 받습니다. 이 트랜잭션은 대화 핸들을 서버에 전달합니다.
다음 예제에서는 서비스 이름 MyServer를 인식하는 서버를 사용하여 시스템 토픽에 대한 대화를 요청합니다. hszServName 및 hszSysTopic 매개 변수는 이전에 문자열 핸들을 만들었습니다.
HCONV hConv; // conversation handle
HWND hwndParent; // parent window handle
HSZ hszServName; // service name string handle
HSZ hszSysTopic; // System topic string handle
hConv = DdeConnect(
idInst, // instance identifier
hszServName, // service name string handle
hszSysTopic, // System topic string handle
(PCONVCONTEXT) NULL); // use default context
if (hConv == NULL)
{
MessageBox(hwndParent, "MyServer is unavailable.",
(LPSTR) NULL, MB_OK);
return FALSE;
}
앞의 예제에서 DdeConnect 인해 MyServer 애플리케이션의 DDE 콜백 함수가 XTYP_CONNECT 트랜잭션을 받습니다.
다음 예제에서 서버는 서버에 전달된 DDEML 핸들을 서버가 지원하는 토픽 이름 문자열 배열의 각 요소와 비교하여 XTYP_CONNECT 트랜잭션에 응답합니다. 서버에서 일치 항목을 찾으면 대화가 설정됩니다.
#define CTOPICS 5
HSZ hsz1; // string handle passed by DDEML
HSZ ahszTopics[CTOPICS]; // array of supported topics
int i; // loop counter
// Use a switch statement to examine transaction types.
// Here is the connect case.
case XTYP_CONNECT:
for (i = 0; i < CTOPICS; i++)
{
if (hsz1 == ahszTopics[i])
return TRUE; // establish a conversation
}
return FALSE; // Topic not supported; deny conversation.
// Process other transaction types.
서버가 XTYP_CONNECT 트랜잭션에 대한 응답으로 TRUE 반환하는 경우 DDEML은 XTYP_CONNECT_CONFIRM 트랜잭션을 서버의 DDE 콜백 함수로 보냅니다. 서버는 이 트랜잭션을 처리하여 대화 핸들을 가져올 수 있습니다.
클라이언트는 서비스 이름 문자열 핸들, 토픽 이름 문자열 핸들 또는 DdeConnect대한 호출에서 둘 다에 대한 NULL 지정하여 와일드카드 대화를 설정할 수 있습니다. 문자열 핸들 중 하나 이상이 NULL 경우 DDEML은 XTYP_WILDCONNECT 트랜잭션을 모든 DDE 애플리케이션의 콜백 함수(XTYP_WILDCONNECT 트랜잭션을 필터링하는 함수 제외)로 보냅니다. 각 서버 애플리케이션은 HSZPAIR 구조체의 null로 끝나는 배열을 식별하는 데이터 핸들을 반환하여 응답해야 합니다. 서버 애플리케이션이 서비스 이름을 등록하기 위해 DdeNameService 호출하지 않은 경우 필터링이 켜진 경우 서버는 XTYP_WILDCONNECT 트랜잭션을 수신하지 않습니다. 데이터 핸들에 대한 자세한 내용은 데이터 관리 참조하세요.
배열에는 클라이언트에서 지정한 쌍과 일치하는 각 서비스 이름 및 토픽 이름 쌍에 대해 하나의 구조가 포함되어야 합니다. DDEML은 대화를 설정할 쌍 중 하나를 선택하고 대화를 식별하는 핸들을 클라이언트에 반환합니다. DDEML은 XTYP_CONNECT_CONFIRM 트랜잭션을 서버로 보냅니다(서버가 이 트랜잭션을 필터링하지 않는 한). 다음 예제에서는 XTYP_WILDCONNECT 트랜잭션에 대한 일반적인 서버 응답을 보여줍니다.
#define CTOPICS 2
UINT uType;
HSZPAIR ahszp[(CTOPICS + 1)];
HSZ ahszTopicList[CTOPICS];
HSZ hszServ, hszTopic;
WORD i, j;
if (uType == XTYP_WILDCONNECT)
{
// Scan the topic list and create an array of HSZPAIR structures.
j = 0;
for (i = 0; i < CTOPICS; i++)
{
if (hszTopic == (HSZ) NULL ||
hszTopic == ahszTopicList[i])
{
ahszp[j].hszSvc = hszServ;
ahszp[j++].hszTopic = ahszTopicList[i];
}
}
// End the list with an HSZPAIR structure that contains NULL
// string handles as its members.
ahszp[j].hszSvc = NULL;
ahszp[j++].hszTopic = NULL;
// Return a handle to a global memory object containing the
// HSZPAIR structures.
return DdeCreateDataHandle(
idInst, // instance identifier
(LPBYTE) &ahszp, // pointer to HSZPAIR array
sizeof(HSZ) * j, // length of the array
0, // start at the beginning
(HSZ) NULL, // no item name string
0, // return the same format
0); // let the system own it
}
클라이언트 또는 서버는 DdeDisconnect 함수를 호출하여 언제든지 대화를 종료할 수 있습니다. 이 함수는 대화에서 파트너의 콜백 함수가 XTYP_DISCONNECT 트랜잭션을 받도록 합니다(파트너가 CBF_SKIP_DISCONNECTS 필터 플래그를 지정하지 않은 경우). 일반적으로 애플리케이션은 DdeQueryConvInfo 함수를 사용하여 종료된 대화에 대한 정보를 얻어 XTYP_DISCONNECT 트랜잭션에 응답합니다. 콜백 함수가 XTYP_DISCONNECT 트랜잭션 처리에서 반환되면 대화 핸들이 더 이상 유효하지 않습니다.
DDE 콜백 함수에서 XTYP_DISCONNECT 트랜잭션을 수신하는 클라이언트 애플리케이션은 DdeReconnect 함수를 호출하여 대화를 다시 설정하려고 시도할 수 있습니다. 클라이언트는 DDE 콜백 함수 내에서 DdeReconnect 호출해야 합니다.
여러 대화
클라이언트 애플리케이션은 DdeConnectList 함수를 사용하여 관심 있는 서버를 시스템에서 사용할 수 있는지 여부를 확인할 수 있습니다. 클라이언트는 DdeConnectList호출할 때 서비스 이름 및 토픽 이름을 지정하므로 DDEML은 XTYP_WILDCONNECT 트랜잭션을 서비스 이름과 일치하는 모든 서버의 DDE 콜백 함수(트랜잭션을 필터링하는 함수 제외)로 브로드캐스트합니다. 서버의 콜백 함수는 HSZPAIR 구조체의 null로 끝나는 배열을 식별하는 데이터 핸들을 반환해야 합니다. 배열에는 클라이언트에서 지정한 쌍과 일치하는 각 서비스 이름 및 토픽 이름 쌍에 대해 하나의 구조가 포함되어야 합니다. DDEML은 서버로 채워진 각 HSZPAIR 구조에 대한 대화를 설정하고 클라이언트에 대화 목록 핸들을 반환합니다. 서버가 이 트랜잭션을 필터링하지 않는 한 서버는 XTYP_CONNECT 트랜잭션을 통해 대화 핸들을 받습니다.
클라이언트는 DdeConnectList호출할 때 서비스 이름, 토픽 이름 또는 둘 다에 NULL 지정할 수 있습니다. 서비스 이름이 NULL 경우 지정된 토픽 이름을 지원하는 시스템의 모든 서버가 응답합니다. 동일한 서버의 여러 인스턴스를 포함하여 각 응답 서버와 대화가 설정됩니다. 항목 이름이 NULL 경우 서비스 이름과 일치하는 각 서버에서 인식되는 각 토픽에 대해 대화가 설정됩니다.
클라이언트는 DdeQueryNextServer 및 DdeQueryConvInfo 함수를 사용하여 DdeConnectList응답하는 서버를 식별할 수 있습니다. DdeQueryNextServer 대화 목록에서 다음 대화 핸들을 반환하고 DdeQueryConvInfoCONVINFO 구조체를 대화에 대한 정보로 채웁니다. 클라이언트는 필요한 대화 핸들을 유지하고 대화 목록에서 나머지를 삭제할 수 있습니다.
다음 예제에서는 DdeConnectList 사용하여 시스템 토픽을 지원하는 모든 서버와 대화를 설정한 다음 DdeQueryNextServer 및 DdeQueryConvInfo 함수를 사용하여 서버의 서비스 이름 문자열 핸들을 가져오고 버퍼에 저장합니다.
HCONVLIST hconvList; // conversation list
DWORD idInst; // instance identifier
HSZ hszSystem; // System topic
HCONV hconv = NULL; // conversation handle
CONVINFO ci; // holds conversation data
UINT cConv = 0; // count of conv. handles
HSZ *pHsz, *aHsz; // point to string handles
// Connect to all servers that support the System topic.
hconvList = DdeConnectList(idInst, NULL, hszSystem, NULL, NULL);
// Count the number of handles in the conversation list.
while ((hconv = DdeQueryNextServer(hconvList, hconv)) != NULL)
cConv++;
// Allocate a buffer for the string handles.
hconv = NULL;
aHsz = (HSZ *) LocalAlloc(LMEM_FIXED, cConv * sizeof(HSZ));
// Copy the string handles to the buffer.
pHsz = aHsz;
while ((hconv = DdeQueryNextServer(hconvList, hconv)) != NULL)
{
DdeQueryConvInfo(hconv, QID_SYNC, (PCONVINFO) &ci);
DdeKeepStringHandle(idInst, ci.hszSvcPartner);
*pHsz++ = ci.hszSvcPartner;
}
// Use the handles; converse with the servers.
// Free the memory and terminate the conversations.
LocalFree((HANDLE) aHsz);
DdeDisconnectList(hconvList);
애플리케이션은 DdeDisconnect 함수를 호출하여 대화 목록에서 개별 대화를 종료할 수 있습니다. 애플리케이션은 DdeDisconnectList 함수를 호출하여 대화 목록의 모든 대화를 종료할 수 있습니다. 두 함수 모두 DDEML이 각 파트너의 DDE 콜백 함수에 XTYP_DISCONNECT 트랜잭션을 보내도록 합니다. DdeDisconnectList 목록의 각 대화 핸들에 대한 XTYP_DISCONNECT 트랜잭션을 보냅니다.
클라이언트는 기존 대화 목록 핸들을 DdeConnectList전달하여 대화 목록에서 대화 핸들 목록을 검색할 수 있습니다. 열거형 프로세스는 목록에서 종료된 대화의 핸들을 제거하고 지정된 서비스 이름과 토픽 이름에 맞는 중복 제거되지 않은 대화가 추가됩니다.
DdeConnectList 기존 대화 목록 핸들을 지정하는 경우 함수는 새 대화의 핸들과 기존 목록의 핸들을 포함하는 새 대화 목록을 만듭니다.
중복 대화가 있는 경우 DdeConnectList는 대화 목록에서 중복된 대화 핸들을 방지하려고. 중복 대화는 동일한 서비스 이름 및 토픽 이름에 동일한 서버가 있는 두 번째 대화입니다. 이러한 두 대화는 서로 다른 핸들을 가지고 있지만 동일한 대화를 식별합니다.