進程通信小結

 

進程:被分配4GB私有地址空間,線程共享這些空間。

進程之間不能互相訪問這種私有地址。

通信方式總結:

 

1,剪切板

 

相關函數

BOOL EmptyClipboard(    

    VOID 
);

BOOL OpenClipboard(      

    HWND hWndNewOwner
);

HANDLE SetClipboardData( 

    UINT uFormat,
    HANDLE 
hMem         // NULL,延遲提交技術,設置空數據塊,當數據接收激活才激活提交
);

BOOL CloseClipboard(  

    VOID 
);

 

Standard Clipboard Formats

The clipboard formats defined by the system are called standard clipboard formats. These clipboard formats are described in the following table.

Value

Meaning

CF_BITMAP

A handle to a bitmap (HBITMAP).

CF_DIB

A memory object containing a BITMAPINFO structure followed by the bitmap bits.

CF_DIBV5

Windows 2000/XP: A memory object containing a BITMAPV5HEADER structure followed by the bitmap color space information and the bitmap bits.

CF_DIF

Software Arts' Data Interchange Format.

CF_DSPBITMAP

Bitmap display format associated with a private format. The hMem parameter must be a handle to data that can be displayed in bitmap format in lieu of the privately formatted data.

CF_DSPENHMETAFILE

Enhanced metafile display format associated with a private format. The hMem parameter must be a handle to data that can be displayed in enhanced metafile format in lieu of the privately formatted data.

CF_DSPMETAFILEPICT

Metafile-picture display format associated with a private format. The hMem parameter must be a handle to data that can be displayed in metafile-picture format in lieu of the privately formatted data.

CF_DSPTEXT

Text display format associated with a private format. The hMem parameter must be a handle to data that can be displayed in text format in lieu of the privately formatted data.

CF_ENHMETAFILE

A handle to an enhanced metafile (HENHMETAFILE).

CF_GDIOBJFIRST through CF_GDIOBJLAST

Range of integer values for application-defined Microsoft Windows Graphics Device Interface (GDI) object clipboard formats. Handles associated with clipboard formats in this range are not automatically deleted using the GlobalFree function when the clipboard is emptied. Also, when using values in this range, the hMem parameter is not a handle to a GDI object, but is a handle allocated by the GlobalAlloc function with the GMEM_MOVEABLE flag.

CF_HDROP

A handle to type HDROP that identifies a list of files. An application can retrieve information about the files by passing the handle to the DragQueryFile functions.

CF_LOCALE

The data is a handle to the locale identifier associated with text in the clipboard. When you close the clipboard, if it contains CF_TEXT data but no CF_LOCALE data, the system automatically sets the CF_LOCALE format to the current input language. You can use the CF_LOCALE format to associate a different locale with the clipboard text.

An application that pastes text from the clipboard can retrieve this format to determine which character set was used to generate the text.

Note that the clipboard does not support plain text in multiple character sets. To achieve this, use a formatted text data type such as Rich Text Format (RTF) instead.

Windows NT/2000/XP: The system uses the code page associated with CF_LOCALE to implicitly convert from CF_TEXT to CF_UNICODETEXT. Therefore, the correct code page table is used for the conversion.

CF_METAFILEPICT

Handle to a metafile picture format as defined by the METAFILEPICT structure. When passing a CF_METAFILEPICT handle by means of Dynamic Data Exchange (DDE), the application responsible for deleting hMem should also free the metafile referred to by the CF_METAFILEPICT handle.

CF_OEMTEXT

Text format containing characters in the OEM character set. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals the end of the data.

CF_OWNERDISPLAY

Owner-display format. The clipboard owner must display and update the clipboard viewer window, and receive the WM_ASKCBFORMATNAME, WM_HSCROLLCLIPBOARD, WM_PAINTCLIPBOARD, WM_SIZECLIPBOARD, and WM_VSCROLLCLIPBOARD messages. The hMem parameter must be NULL.

CF_PALETTE

Handle to a color palette. Whenever an application places data in the clipboard that depends on or assumes a color palette, it should place the palette on the clipboard as well.

 

If the clipboard contains data in the CF_PALETTE (logical color palette) format, the application should use the SelectPalette and RealizePalette functions to realize (compare) any other data in the clipboard against that logical palette.

When displaying clipboard data, the clipboard always uses as its current palette any object on the clipboard that is in the CF_PALETTE format.

CF_PENDATA

Data for the pen extensions to the Microsoft Windows for Pen Computing.

CF_PRIVATEFIRST through CF_PRIVATELAST

Range of integer values for private clipboard formats. Handles associated with private clipboard formats are not freed automatically; the clipboard owner must free such handles, typically in response to the WM_DESTROYCLIPBOARD message.

CF_RIFF

Represents audio data more complex than can be represented in a CF_WAVE standard wave format.

CF_SYLK

Microsoft Symbolic Link (SYLK) format.

CF_TEXT

Text format. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals the end of the data. Use this format for ANSI text.

CF_WAVE

Represents audio data in one of the standard wave formats, such as 11 kHz or 22 kHz Pulse Code Modulation (PCM).

CF_TIFF

Tagged-image file format.

CF_UNICODETEXT

Windows NT/2000/XP: Unicode text format. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals the end of the data.

 

 

HGLOBAL GlobalAlloc(
 
UINT uFlags,
  SIZE_T dwBytes
);

Win32平臺下沒有全局堆和本地堆區別。

uFlags

[in] Memory allocation attributes. If zero is specified, the default is GMEM_FIXED. This parameter can be one or more of the following values, except for the incompatible combinations that are specifically noted.

Value

Meaning

GHND

0x0042

Combines GMEM_MOVEABLE and GMEM_ZEROINIT.

GMEM_FIXED

0x0000

Allocates fixed memory. The return value is a pointer.

GMEM_MOVEABLE

0x0002

Allocates movable memory. Memory blocks are never moved in physical memory, but they can be moved within the default heap.

The return value is a handle to the memory object. To translate the handle into a pointer, use the GlobalLock function.

This value cannot be combined with GMEM_FIXED.

GMEM_ZEROINIT

0x0040

Initializes memory contents to zero.

GPTR

0x0040

Combines GMEM_FIXED and GMEM_ZEROINIT.

 

LPVOID GlobalLock(
 
HGLOBAL hMem
);

生成文本拷貝的代碼:

if(OpenClipboard())

{

CString str;

HANDLE hClip;

char *pBuf;

EmptyClipboard();

GetDlgItemText(IDC_EDIT_SEND,str);

hClip=GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1);

pBuf=(char*)GlobalLock(hClip);

strcpy(pBuf,str);

GlobalUnlock(hClip);

SetClipboardData(CF_TEXT,hClip);

CloseClipboard();

}

 

接受文本拷貝的代碼

if(OpenClipboard())

{

if(IsClipboardFormatAvailable(CF_TEXT)) // 判定剪切板數據格式

{

HANDLE hClip;

char *pBuf;

hClip=GetClipboardData(CF_TEXT);

pBuf=(char*)GlobalLock(hClip);

GlobalUnlock(hClip);

SetDlgItemText(IDC_EDIT_RECV,pBuf);

CloseClipboard();

}

}

 

 

2,匿名管道

 

匿名管道只能在父子進程之間通信

---------------父進程-----------

BOOL CreatePipe(
 
PHANDLE hReadPipe,
  PHANDLE hWritePipe,
  LPSECURITY_ATTRIBUTES lpPipeAttributes, // don't set null
  DWORD nSize  // 0,使用缺省的緩衝區大小
);

typedef struct _SECURITY_ATTRIBUTES {

DWORD nLength;

LPVOID lpSecurityDescriptor;

BOOL bInheritHandle;  // whether can be inherited
} SECURITY_ATTRIBUTES,

*PSECURITY_ATTRIBUTES;

 

BOOL CreateProcess(
 
LPCTSTR lpApplicationName,
  LPTSTR lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL bInheritHandles,
  DWORD dwCreationFlags,
  LPVOID lpEnvironment,
  LPCTSTR lpCurrentDirectory,
  LPSTARTUPINFO lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);

typedef struct _STARTUPINFO {

DWORD cb;

LPTSTR lpReserved;

LPTSTR lpDesktop;

LPTSTR lpTitle;

DWORD dwX;

DWORD dwY;

DWORD dwXSize;

DWORD dwYSize;

DWORD dwXCountChars;

DWORD dwYCountChars;

DWORD dwFillAttribute;

DWORD dwFlags;

WORD wShowWindow;

WORD cbReserved2;

LPBYTE lpReserved2;

HANDLE hStdInput;

HANDLE hStdOutput;

HANDLE hStdError;
} STARTUPINFO,

*LPSTARTUPINFO;

 

typedef struct _PROCESS_INFORMATION {

HANDLE hProcess;

HANDLE hThread;

DWORD dwProcessId;

DWORD dwThreadId;
} PROCESS_INFORMATION,

*LPPROCESS_INFORMATION;

 

 

首先,構造

private:

HANDLE hWrite;

HANDLE hRead;

 

if(hRead)

CloseHandle(hRead);

if(hWrite)

CloseHandle(hWrite);

 

創建管道代碼:

SECURITY_ATTRIBUTES sa;

sa.bInheritHandle=TRUE;

sa.lpSecurityDescriptor=NULL;

sa.nLength=sizeof(SECURITY_ATTRIBUTES);

if(!CreatePipe(&hRead,&hWrite,&sa,0))

{

MessageBox("創建匿名管道失敗!");

return;

}

 

STARTUPINFO sui;

PROCESS_INFORMATION pi;

ZeroMemory(&sui,sizeof(STARTUPINFO));

sui.cb=sizeof(STARTUPINFO);

sui.dwFlags=STARTF_USESTDHANDLES;

sui.hStdInput=hRead;            // 子進程的標準輸入句柄

sui.hStdOutput=hWrite;      //  子進程的標準輸出句柄

sui.hStdError=GetStdHandle(STD_ERROR_HANDLE); // 標準錯誤句柄

 

if(!CreateProcess("..//Child//Debug//Child.exe",NULL,NULL,NULL,

TRUE,0,NULL,NULL,&sui,&pi))    //  創建子進程

{

CloseHandle(hRead);

CloseHandle(hWrite);

hRead=NULL;

hWrite=NULL;

MessageBox("創建子進程失敗!");

return;

}

else

{

// 如果父進程不使用內核對象句柄

CloseHandle(pi.hProcess);

CloseHandle(pi.hThread);

}

 

管道讀取

char buf[100];

DWORD dwRead;

if(!ReadFile(hRead,buf,100,&dwRead,NULL))

{

MessageBox("讀取數據失敗!");

return;

}

MessageBox(buf);

 

管道寫入

char buf[]="http://www.sunxin.org";

DWORD dwWrite;

if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))

{

MessageBox("寫入數據失敗!");

return;

}

 

---------------子進程-----------

 

private:

HANDLE hWrite;

HANDLE hRead;

 

hRead=NULL;

hWrite=NULL;

 

if(hRead)

CloseHandle(hRead);

if(hWrite)

CloseHandle(hWrite);

 

在窗口創建完畢後調用:

hRead=GetStdHandle(STD_INPUT_HANDLE);

hWrite=GetStdHandle(STD_OUTPUT_HANDLE);

 

void CChildView::OnPipeRead()

{

// TODO: Add your command handler code here

char buf[100];

DWORD dwRead;

if(!ReadFile(hRead,buf,100,&dwRead,NULL))

{

MessageBox("讀取數據失敗!");

return;

}

MessageBox(buf);

}

 

void CChildView::OnPipeWrite()

{

// TODO: Add your command handler code here

char buf[]="匿名管道測試程序";

DWORD dwWrite;

if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))

{

MessageBox("寫入數據失敗!");

return;

}

}

 

父子關係的確認,必須通過CreateProcess由父進程來啓動子進程。

 

 

 

3,命名管道

命名管道是通過網絡來完成進程間的通信,它屏蔽了底層的網絡協議細節。我們在不瞭解網絡協議的情況下,也可以利用命名管道來實現進程間的通信。 命名管道充分利用了Windows NTWindows 2000內建的安全機制 將命名管道作爲一種網絡編程方案時,它實際上建立了一個客戶機/服務器通信體系,並在其中可靠地傳輸數據 命名管道是圍繞Windows文件系統設計的一種機制,採用命名管道文件系統(Named Pipe File SystemNPFS)接口,因此,客戶機和服務器可利用標準的Win32文件系統函數(例如:ReadFileWriteFile)來進行數據的收發。

 

命名管道服務器和客戶機的區別在於:服務器是唯一一個有權創建命名管道的進程,也只有它才能接受管道客戶機的連接請求。而客戶機只能同一個現成的命名管道服務器建立連接。 命名管道服務器只能在Windows NTWindows 2000上創建,所以,我們無法在兩臺Windows 95Windows 98計算機之間利用管道進行通信。不過,客戶機可以是Windows 95Windows 98計算機,與Windows NTWindows 2000計算機進行連接通信。

命名管道提供了兩種基本通信模式:字節模式和消息模式。在字節模式中,數據以一個連續的字節流的形式,在客戶機和服務器之間流動。而在消息模式中,客戶機和服務器則通過一系列不連續的數據單位,進行數據的收發,每次在管道上發出了一條消息後,它必須作爲一條完整的消息讀入。

 

 

HANDLE CreateNamedPipe(
 
LPCTSTR lpName,
  DWORD dwOpenMode,
  DWORD dwPipeMode,
  DWORD nMaxInstances,  //同一個命名管道能夠創建的客戶端實例 1~PIPE_UNLIMITED_INSTANCES
  DWORD nOutBufferSize,
  DWORD nInBufferSize,
  DWORD nDefaultTimeOut,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes
);

 

 

BOOL ConnectNamedPipe(
 
HANDLE hNamedPipe,
  LPOVERLAPPED lpOverlapped
);
// 命名管道的服務端等待客戶端連接的到來

HANDLE CreateEvent(
 
LPSECURITY_ATTRIBUTES lpEventAttributes,
  BOOL bManualReset,
  BOOL bInitialState,
  LPCTSTR lpName
);

 

----------------命名管道的服務端程序----------------

private:

HANDLE hPipe; //

 

hPipe=NULL;

 

if(hPipe)

CloseHandle(hPipe);

 

創建命名管道

hPipe=CreateNamedPipe("////.//pipe//MyPipe",

PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,// 雙向和重疊方式

0, // 字節方式

1,// 管道實例的最大數目

1024,1024,// 輸入和輸出的緩衝區大小

0,// 超時

NULL);

if(INVALID_HANDLE_VALUE==hPipe)

{

MessageBox("創建命名管道失敗!");

hPipe=NULL;

return;

}

HANDLE hEvent;

hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); // 匿名事件對象

if(!hEvent)

{

MessageBox("創建事件對象失敗!");

CloseHandle(hPipe);

hPipe=NULL;

return;

}

OVERLAPPED ovlap;

ZeroMemory(&ovlap,sizeof(OVERLAPPED)); // 清零

ovlap.hEvent=hEvent;

if(!ConnectNamedPipe(hPipe,&ovlap))

{

if(ERROR_IO_PENDING!=GetLastError())

{

MessageBox("等待客戶端連接失敗!");

CloseHandle(hPipe);

CloseHandle(hEvent);

hPipe=NULL;

return;

}

}

if(WAIT_FAILED==WaitForSingleObject(hEvent,INFINITE))

{

MessageBox("等待對象失敗!");

CloseHandle(hPipe);

CloseHandle(hEvent);

hPipe=NULL;

return;

}

CloseHandle(hEvent);

 

讀取代碼

char buf[100];

DWORD dwRead;

if(!ReadFile(hPipe,buf,100,&dwRead,NULL))

{

MessageBox("讀取數據失敗!");

return;

}

MessageBox(buf);

 

寫入代碼

char buf[]="http://blog.csdn.net/persuper/";

DWORD dwWrite;

if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))

{

MessageBox("寫入數據失敗!");

return;

}

 

 

-----------命名管道的客戶端程序----------------

 

BOOL WaitNamedPipe(
 
LPCTSTR lpNamedPipeName,
  DWORD nTimeOut
);

 

HANDLE CreateFile(
 
LPCTSTR lpFileName,
  DWORD dwDesiredAccess,
  DWORD dwShareMode,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  DWORD dwCreationDisposition,
  DWORD dwFlagsAndAttributes,
  HANDLE hTemplateFile
);

 

定義句柄變量

private:

HANDLE hPipe;

 

hPipe=NULL;

 

if(hPipe)

CloseHandle(hPipe);

 

建立管道連接

if(!WaitNamedPipe("////.//pipe//MyPipe",NMPWAIT_WAIT_FOREVER)) // 一直等待到有管道可用

{

MessageBox("當前沒有可利用的命名管道實例!");

return;

}

hPipe=CreateFile("////.//pipe//MyPipe",GENERIC_READ | GENERIC_WRITE,

0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

if(INVALID_HANDLE_VALUE==hPipe)

{

MessageBox("打開命名管道失敗!");

hPipe=NULL;

return;

}

讀取

 

char buf[100];

DWORD dwRead;

if(!ReadFile(hPipe,buf,100,&dwRead,NULL))

{

MessageBox("讀取數據失敗!");

return;

}

MessageBox(buf);

 

寫入

 

char buf[]="命名管道測試程序";

DWORD dwWrite;

if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))

{

MessageBox("寫入數據失敗!");

return;

}

 

 

4,郵槽

郵槽是基於廣播通信體系設計出來的,它採用無連接的不可靠的數據傳輸。 郵槽是一種單向通信機制,創建郵槽的服務器進程讀取數據,打開郵槽的客戶機進程寫入數據 爲保證郵槽在各種Windows平臺下都能夠正常工作,我們傳輸消息的時候,應將消息的長度限制在424字節以下。

 

HANDLE CreateMailslot(
 
LPCTSTR lpName,
  DWORD nMaxMessageSize,
  DWORD lReadTimeout,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes
);

 

-----------油槽服務器程序----------------

接受數據

HANDLE hMailslot;

hMailslot=CreateMailslot("////.//mailslot//MyMailslot",0,

MAILSLOT_WAIT_FOREVER,NULL);

if(INVALID_HANDLE_VALUE==hMailslot)

{

MessageBox("創建油槽失敗!");

return;

}

char buf[100];

DWORD dwRead;

if(!ReadFile(hMailslot,buf,100,&dwRead,NULL))

{

MessageBox("讀取數據失敗!");

CloseHandle(hMailslot);

return;

}

MessageBox(buf);

CloseHandle(hMailslot);

 

-----------油槽客戶端程序----------------

發送數據

HANDLE hMailslot;

hMailslot=CreateFile("////.//mailslot//MyMailslot",GENERIC_WRITE,

FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

if(INVALID_HANDLE_VALUE==hMailslot)

{

MessageBox("打開油槽失敗!");

return;

}

char buf[]="http://www.sunxin.org";

DWORD dwWrite;

if(!WriteFile(hMailslot,buf,strlen(buf)+1,&dwWrite,NULL))

{

MessageBox("寫入數據失敗!");

CloseHandle(hMailslot);

return;

}

CloseHandle(hMailslot);

 

編寫會議通知系統,實現一對多的廣播通信

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章