进程通信小结

 

进程:被分配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);

 

编写会议通知系统,实现一对多的广播通信

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