32 位元 Windows 各進程擁有獨立位址空間,無法直接存取彼此記憶體。IPC 方案包括:剪貼板、共享記憶體、管道、Socket、COM、DDE。DDE (Dynamic Data Exchange) 為 Windows 早期標準協議,建於訊息系統與共享記憶體之上,適合簡單資料交換、啟動關聯應用。本文實作一個 DDE 伺服器/客戶端合一程式,雙擊執行兩個實例即可互通。
程式啟動即註冊為 Server,並嘗試連接另一實例作為 Client。雙向熱連結交換兩項資料:
#define NITEM 2
const char szApp[] = "DDEDemoServer";
const char szTopic[] = "Topic";
const char* pszItem[NITEM] = {"Item1", "Item2"};
int count = 0;
CString ServerData[NITEM];
HCONV hConv = 0;
DWORD idInst = 0;
HWND hWnd = 0;
HSZ hszApp = 0, hszTopic = 0, hszItem[NITEM];
BOOL bConnect = FALSE;
HDDEDATA CALLBACK DdeCallback(UINT wType, UINT wFmt, HCONV hConv, HSZ hszTopic, HSZ hszItem,
HDDEDATA hData, DWORD dwData1, DWORD dwData2) {
char buf[256];
switch (wType) {
case XTYP_CONNECT:
case XTYP_ADVSTART:
return (HDDEDATA)TRUE; // 允許連線/建議
case XTYP_ADVDATA: // 客戶端收到伺服器推送資料
for (int i = 0; i < NITEM; i++) {
if (hszItem == hszItem[i]) {
DdeGetData(hData, (LPBYTE)buf, 255, 0);
SetDlgItemText(hWnd, (i==0)?IDC_STATIC2:IDC_STATIC3, buf);
}
}
return (HDDEDATA)DDE_FACK;
case XTYP_REQUEST: // 客戶端主動請求
case XTYP_ADVREQ: // 熱連結定期請求
for (int i = 0; i < NITEM; i++) {
if (hszItem == hszItem[i]) {
return DdeCreateDataHandle(idInst, (LPBYTE)(LPCTSTR)ServerData[i],
ServerData[i].GetLength()+1, 0, hszItem, wFmt, 0);
}
}
break;
}
return 0;
}
BOOL CDdeDemoDlg::OnInitDialog() {
// ... 圖示、選單初始化 ...
hWnd = m_hWnd;
if (DdeInitialize(&idInst, (PFNCALLBACK)DdeCallback,
APPCMD_FILTERINITS | CBF_FAIL_EXECUTES | CBF_SKIP_CONNECT_CONFIRMS |
CBF_FAIL_SELFCONNECTIONS | CBF_FAIL_POKES, 0)) {
MessageBox(_T("DDE 初始化失敗!")); return FALSE;
}
hszApp = DdeCreateStringHandle(idInst, szApp, CP_WINANSI);
hszTopic = DdeCreateStringHandle(idInst, szTopic, CP_WINANSI);
for (int i=0; i
void CDdeDemoDlg::OnTimer(UINT nIDEvent) {
count++;
ServerData[1].Format(_T("%d"), count);
SetDlgItemText(IDC_STATIC1, ServerData[1]);
DdePostAdvise(idInst, hszTopic, hszItem[1]); // 推送計數器更新
if (!bConnect) { // 嘗試連線另一實例
hConv = DdeConnect(idInst, hszApp, hszTopic, NULL);
if (hConv) {
bConnect = TRUE;
DWORD dwResult;
for (int i=0; i
void CDdeDemoDlg::OnChangeEdit1() {
UpdateData();
ServerData[0] = m_edit;
DdePostAdvise(idInst, hszTopic, hszItem[0]); // 推送字串更新
}
void CDdeDemoDlg::OnDestroy() {
KillTimer(1);
DdeNameService(idInst, 0, 0, DNS_UNREGISTER); // 註銷服務
DdeFreeStringHandle(idInst, hszApp);
DdeFreeStringHandle(idInst, hszTopic);
for (int i=0; i
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| DDE | 簡單、系統內建、跨語言 | 效能低、功能少、漸被淘汰 | 簡單資料交換、舊系統整合 |
| 共享記憶體 + Event | 極高效能、大資料量 | 需同步機制、複雜 | 高頻大量資料交換 |
| Named Pipe | 雙向、網路透明、安全性 | 程式碼較多 | 本機/跨機進程通訊 |
| Socket (TCP/UDP) | 跨平台、跨網路、標準 | 協議設計、連線管理 | 分散式系統、網路通訊 |
| COM / ATL | 物件導向、語言中立、註冊管理 | 學習曲線陡峭 | 元件化架構、跨語言元件 |