維尼的蜂巢

RealTime??!! It’s amazing!!!!

兩隻程式間的溝通 三月 1, 2006

Filed under: VC++/C++/C — kevinlin @ 12:54 上午

要讓兩隻程式做訊息的溝通 有三個方法

方法1  :GetWindow and PostMessage
方法2  :CreateFileMapping
方法3  :TCPIP

下面是方法2的實作

這個方法, 對於在同一login user下, 只有兩個程式溝通的情況下, 是可以work的, 而且效率上來講也還不錯. (註: 至於用ini檔, 以及pipe, 在效率上都差很多, 而且錯誤處理上也會比較麻煩). 不過這個方法有幾個缺點:
1.多對一的情況下無法適用: 事實上, 可以採用Client在需要Server服務前, 先發送一個要求服務的訊息, 由Server給定一個handle, 做為後續使用共享記憶體名稱的依據, 而在之後Client對Server的呼叫, 都給定這個handle做為訊息參數. 這樣的處理也是能達到多對一的服務.
2.不同login user下無法適用: 如果client是一個COM元件,由Web ASP程式啟動,很抱歉,你用FindWindow也無法找到Server的Window,因為兩者分屬不同的login user.

*** Client端 (發送訊息者):

static HWND Client_Window = NULL;
static HWND Server_Window = NULL;
static HANDLE Client_Memory_Handle = NULL;

LRESULT CALLBACK system_msg_proc(HWND hwnd, Uint message, WPARAM wparam, LPARAM lparam)
{
  return DefWindowProc(hwnd,message,wparam,lparam);
}

1.初始化

// 登錄window class
const char* client_name = “ClientWindow"; // 名稱請自定…
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = (WNDPROC)system_msg_proc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = instance; // 請自行取得
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = client_name;
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
// 建立通訊視窗
Client_Window = CreateWindow(client_name,client_name,WS_POPUP | WS_CAPTION,0,0,0,0,NULL,NULL,instance,NULL);
if (Client_Window == NULL) 錯誤處理…
// 尋找Server視窗
const char* server_name = “ServerWindow"; // 名稱請自定
Server_Window = FindWindow(server_name,server_name);
if (Server_Window == NULL) 錯誤處理…

2.傳送訊息前建立共享記憶體

const char *filename = “ClientMemory";
int len = 資料長度
Client_Memory = CreateFileMapping(INVALID_HANDLE_VALUE,0,PAGE_READWRITE,0,len,filename);
if (Client_Memory == NULL) 錯誤處理
char* buffer = (char*)MapViewOfFile(Client_Memory,FILE_MAP_READ | FILE_MAP_WRITE,0,0,0);
if (buffer == NULL) 錯誤處理
將資料寫入buffer中
UnmapViewOfFile(buffer);
// 注意,寫完不能立即將共享記憶體close, 必須等Server端處理完後才能close

3.傳送並等待訊息

if (!PostMessage(Server_Window,WM_USER,額外參數,(long)m_DLL_Window)) 錯誤處理
// 以下等待的函數, 可另行再做Timeout的控制
for (;;)
{
  MSG msg;
  if (! PeekMessage(&msg,Client_Window,0,0,PM_REMOVE))
  {
    Sleep(50);
    continue;
  }
  if ((msg.hwnd == m_Client_Window) && (msg.message == WM_USER) &&
     (msg.lParam == (long)Server_Window))
  {
    接收到回傳訊息,加以處理
     將Client_Memory關閉
     break;
  }
  TranslateMessage(&msg);
  DispatchMessage(&msg);
}

*** Server端

static HWND Server_Window = NULL;

1.初始化

const char *name = “ServerWindow"; // 名稱請自定
// 登錄window class
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = (WNDPROC)system_msg_proc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = instance;
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = name;
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
// 建立通訊視窗
Server_Window = CreateWindow(name,name,WS_POPUP | WS_CAPTION,0,0,0,0,NULL,NULL,instance,NULL);
if (Server_Window != NULL) 錯誤處理

2. 訊息處理函數

LRESULT CALLBACK system_msg_proc(HWND hwnd, Uint message, WPARAM wparam, LPARAM lparam)
{
  switch(message)
  {
   case WM_USER:
     process_call(wparam,(HWND)lparam);
     break;
   default:
     return DefWindowProc(hwnd,message,wparam,lparam);
  }
  return 0;
}

void process_call(unsigned int wparam, HWND back_window)
{
  // 開啟共享記憶體加以處理
  const char* filename = “ClientMemory";
  HANDLE handle = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,0,filename);
  if (handle == NULL) 錯誤處理
  char* buffer = (char*) MapViewOfFile(handle,FILE_MAP_READ | FILE_MAP_WRITE,0,0,0);
  if (buffer == NULL) 錯誤處理
  處理Client傳來的資料
  UnmapViewOfFile(buffer);
  CloseHandle(handle);
  // 回傳訊息給Client (註: 此處可以再建個Share Memory,將資料傳回給Client處理)
  PostMessage(back_window,WM_USER,額外參數,(long)Server_Window);
}

 

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 變更 )

Twitter picture

You are commenting using your Twitter account. Log Out / 變更 )

Facebook照片

You are commenting using your Facebook account. Log Out / 變更 )

Google+ photo

You are commenting using your Google+ account. Log Out / 變更 )

連結到 %s