一、邮槽(MailSlot)
一、介绍
(一)邮槽是最为简单的进程间数据共享方式,一个进程创建并拥有一个邮槽,其他进程都可以打开这个邮槽并向其发送消息。
(二)进程分为客户端和服务端。
1.服务端创建邮槽。
2.客户端通过邮槽,将消息传送或广播给一个或多个服务器进程。
3.服务端读取。
所以这种通信是单向的,而且支持本机间、网络间进程通信。
(三)最多424个字节,任意格式。
(四)邮槽是一种虚拟文件,对邮槽的操作与对文件操作相似。
二、基本操作:
(一)邮槽命名
本机进程间通信:
\\.\mailslot\[path\]name 其中“.”代表在本机上通信,path是路径,name是邮槽名字
不同主机间通信:
\\DomainName\\mailslot\[path\]name 其中DomainName是域名,
\\ComputerName\\mailslot\[path\]name 其中ComputerName是计算机名
可以使用通配符进行广播
\\* \mailslot\[path\]name
(二)服务端实现(以本机通信为例)
//建立一个邮槽
HANDLE hMailslot;
hMailslot = CreateMailslot(_T("\\\\.\\mailslot\\MyMailslot"), 0, MAILSLOT_WAIT_FOREVER, NULL);
//像读文件一样从邮槽读取数据
TCHAR buf[400]; //buf里面存的是读取到的数据
ZeroMemory(buf, 400);
DWORD dwRead;
ReadFile(hMailslot, buf, 400, &dwRead, NULL)
//关闭邮槽
CloseHandle(hMailslot);
(三)客户端实现
//像打开一个文件一样打开服务端建立的邮槽
HANDLE hMailSlot;
hMailSlot = CreateFile(_T("\\\\.\\mailslot\\MyMailslot"), GENERIC_WRITE, FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
//向邮槽中写入数据
TCHAR buf[400]; //buf里面存的是写入的数据
ZeroMemory(buf, 400);
DWORD dwWrite;
WriteFile(hMailSlot, buf, 400, &dwWrite, NULL)
//关闭邮槽
CloseHandle(hMailSlot);
三、DEMO
Demo用控制台程序实现一个客户端向一个服务端发送数据。
MailslotS是服务端,MailslotC是客户端。
二、管道
一、介绍
(一)管道是一种用于在进程间共享数据的机制,其实质是一段共享内存,可以看作一种特殊的文件。由一个进程读、另一个进程写,类似于一个管道两端,因此这种进程间的通信方式称作“管道”。
(二)管道分为匿名管道和命名管道。
匿名管道只能在父子进程间进行通信,不能在网络间通信,而且数据传输是单向的,只能一端写,另一端读。命令管道可以在任意进程间通信,通信是双向的,任意一端都可读可写,但是在同一时 间只能有一端读、一端写。
二、基本操作:
(一)创建命名管道
HANDLE WINAPI CreateNamedPipe(
LPCTSTR lpName,
DWORD dwOpenMode,
DWORD dwPipeMode,
DWORD nMaxInstances,
DWORD nOutBufferSize,
DWORD nInBufferSize,
DWORD nDefaultTimeOut,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
参数说明:
LPCTSTR lpName
表示管道名称,采用的形式是:\\.\pipe\pipename。最多可达256个字符的长度,而且不区分大小写。如果已经有同名管道,则会创建那个管道的一个新实例。
DWORD dwOpenMode
表示管道的打开方式。最常用的三种:
1.PIPE_ACCESS_DUPLEX
该管道是双向的,服务器和客户端进程都可以从管道读取或者向管道写入数据。
2.PIPE_ACCESS_INBOUND
该管道中数据是从客户端流向服务端,即客户端只能写,服务端只能读。
3.PIPE_ACCESS_OUTBOUND
该管道中数据是从服务端流向客户端,即客户端只能读,服务端只能写。
第三个参数DWORD dwPipeMode
表示管道的模式,常用模式:
1.PIPE_TYPE_BYTE
数据作为一个连续的字节数据流写入管道。
2.PIPE_TYPE_MESSAGE
数据用数据块(名为“消息”或“报文”)的形式写入管道。
3.PIPE_READMODE_BYTE
数据以单独字节的形式从管道中读出。
4.PIPE_READMODE_MESSAGE
数据以名为“消息”的数据块形式从管道中读出(要求指定PIPE_TYPE_MESSAGE)。
5.PIPE_WAIT
同步操作在等待的时候挂起线程。
6.PIPE_NOWAIT
同步操作立即返回。
DWORD nMaxInstances
表示该管道所能够创建的最大实例数量。必须是1到常数PIPE_UNLIMITED_INSTANCES间的一个值。在WINBASE.H中有#define PIPE_UNLIMITED_INSTANCES 255
DWORD nOutBufferSize
表示管道的输出缓冲区容量,为0表示使用默认大小。
DWORD nInBufferSize
表示管道的输入缓冲区容量,为0表示使用默认大小。
DWORD nDefaultTimeOut
表示管道的默认等待超时。
LPSECURITY_ATTRIBUTES lpSecurityAttributes
表示管道的安全属性。
函数返回值:
函数执行成功返回命名管道的句柄,否则返回INVALID_HANDLE_VALUE。
(二)等待客户端连接命名管道
BOOLWINAPI ConnectNamedPipe(HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped);
函数说明:
第一个参数表示命名管道的句柄。
第二个参数是一个指向OVERLAPPED结构的指针。
(三)客户端连接命名管道
BOOLWINAPI WaitNamedPipe(LPCTSTR lpNamedPipeName, DWORD nTimeOut);
函数说明:
LPCTSTR lpNamedPipeName
表示管道名称,采用的形式是:\\servername\pipe\pipename。如果是本机管道,servername用“.”来表示。
DWORD nTimeOut
表示等待命名管道的一个实例有效的超时时间,单位毫秒。也可以用NMPWAIT_USE_DEFAULT_WAIT表示使用命名管道的设定值(在调用CreateNamedPipe创建命名管道时指定的),NMPWAIT_WAIT_FOREVER表示无限等待。
函数返回值:
在指定时间内连接成功返回TRUE,否则返回FALSE。
三、DEMO
服务端和客户端的主要步骤如下所示:
1. 服务端用CreateNamedPipe创建一个命名管道并使用ConnectNamedPipe等待客户端的连接。
2. 客户端使用WaitNamedPipe连接成功后,用CreateFile打开管道并使用WriteFile向管道中写入一段数据(即向服务端发送消息)。
3. 服务端使用ReadFile从管道中读取数据后(即收到消息)再向管道中写入确认信息表明已经收到客户端传输的数据(即通知客户端已收到)。
4. 客户端收到确认信息后结束,调用CloseHandle关闭管道(该管道是CreateFile打开的)。
5.服务端使用DisconnectNamedPipe和CloseHandle关闭管道。
PS:真正运用的话,还需要考虑PV之类的操作。三、套接字(Socket )
一、介绍
借用了Socket 通信的原理。(任何可以在两台主机间进行网络数据通信的机制都可以用于进程间通信)。如果在一台主机上既使用 Socket 服务端又实现 Socket 客户端,那么客户端在连接服务端时将 IP 指定为本机,就可以实现同一主机上的 Socket 服务端进程和 Socket 客户端进程间的通信了。
使用 Socket 进行进程间通信既可以实现实时性,又可以传输大数据量信息,且数据传输的速度也很快,因此应用范围很广泛。
二、基本操作:
1.WSAStartup() 函数的功能是加载 Ws2_32.dll 等 Socket 程序运行的环境。
2.WSACleanup() 函数。与 WSAStartup 的功能相反,WSACleanup 释放 Ws2_32.dll 库,函数无参数。
3.Socket()函数的功能是建立一个绑定到指定协议和传输类型的 Socket。
4.connect()函数的功能是与服务端建立连接。这个函数只能由服务端程序调用。
5.sockaddr、SOCKADDR、sockaddr_in、SOCKADDR IN 结构。 这几个结构用于表示地址和端口。在 IPv4 下,这几个结构可以通用。
6.send() 函数。send 函数的功能是向连接的另一端发送数据
7.recv()函数的功能是从连接的另外一端接收数据
8.colsesocket()函数用于关闭 Socket
9.bind()函数的功能是将 Socket 与网络地址和端口绑定起来
10.listen()函数的功能是将 Socket 的状态设置为监听,以使客户端程序可以进行连接
11.accept()函数的功能是接收客户端的连接,accept 函数直到客户端有连接后才会返回。
三、DEMO
demo实现服务端监听,如果有客户端请求链接,就开一个线程开始传数据。
(一)客户端程序
1.客户端程序在运行后,首先需要使调用 WSAStartup 函数,确保进程加载 socket 应
用程序所必须的环境和库文件,如 Ws2_32.dll。
2.调用函数 Socket 创建 SOCKET,在创建时需指定使用的网络协议、连接类型等。
3.填充 SOCKADDR 结构,指定服务端的地址、端口等。
4.调用 connect 函数连接到服务端。
5.如果连接成功,就可以使用 send 和 recv 函数发送和接收数据。
6.在数据传输完成后,可调用 closesocket 函数关闭 Socket。
7.调用 WSACleanup 函数释放资源。
(二)服务端程序
1.程序在运行后,首先需要使调用 WSAStartup 加载 Ws2_32.dll。
2.调用函数 socket 创建用于监听的 SOCKET,在创建时需指定使用的网络协议、连接
类型等。
3.调用 bind 函数将 Socket 绑定到网络地址和端口。
4.调用 listen 函数开始监听。
5.调用 accept 函数等待客户端连接。在客户端连接后,accept 函数返回,得到连接
Socket。在 accept 函数返回后,可立即再调用,以处理其他客户端的连接。
6.得到连接 Socket 后,可调用 send 和 recv 发送、接收数据。
7.在数据传输完成后,可调用 closesocket 函数关闭 Socket。
8.调用 WSACleanup 函数释放 DLL。四、自定义消息
WM_COPYDATA是一种非常强大却鲜为人知的消息。当一个应用向另一个应用传送数据时,发送方只需使用调用SendMessage函数,参数是目 的窗口的句柄、传递数据的起始地址、M_COPYDATA消息。接收方只需像处理其它消息那样处理WM_COPY DATA消息,这样收发双方就实现了 数据共享。
WM_COPYDATA是一种非常简单的方法,它在底层实际上是通过文件映射来实现的。
它的缺点是灵活性不高,并且它只能用于Windows平台的单机环境下。
五、文件映射(Memory-Mapped Files)
使进程把文件内容当作进程地址区间一块内存那样来对待。因此,进程不必使用文件I/O操作,
只需简单的指针操作就可读取和修改文件的内容。
Win32 API允许多个进程访问同一文件映射对象,各个进程在它自己的地址空间里接收内存的指针。通过使用这些指针,不同进程就可以读或修改文件的内容,实现了对文件中数据的共享。
六、剪贴板
剪贴板是最常用的系统特性之一。
剪贴板由系统定义,并不属于任何一个特定的进程。系统中所有进程都可以访问和设置剪贴板。剪贴板最大的特点就是数据传输没有明确的目标,数据是被动访问的,设置剪贴板的程序并不知道所设置的数据什么时候被访问,也不知道被哪个进程访问,剪贴板中的内容也可以多次访问,直到新的数据写入。正是此特性决定了剪贴板便于计算机用户进行直接操作。
因此通过剪贴板也是一种可供选择的进程间通信方式。但是由于系统中任何一个进程都 可以无限制地访问剪贴板,剪贴板也是一种不可靠的通信方式。
七、动态数据交换
动态数据交换(DDE)是使用共享内存在应用程序之间进行数据交换的一种进程间通信形式。应用程序可以使用DDE进行一次性数据传输,也可以当出现新数据时,
通过发送更新值在应用程序间动态交换数据。
DDE和剪贴板一样既支持标准数据格式(如文本、位图等),又可以支持自己定义的数据格式。但它们的数据传输机制却不同,一个明显区别是剪贴板操作几乎
总是用作对用户指定操作的一次性应答-如从菜单中选择Paste命令。尽管DDE也可以由用户启动,但它继续发挥作用一般不必用户进一步干预。DDE有三 种数据交换方式:
(1) 冷链:数据交换是一次性数据传输,与剪贴板相同。
(2) 温链:当数据交换时服务器通知客户,然后客户必须请求新的数据。
(3) 热链:当数据交换时服务器自动给客户发送数据。
DDE交换可以发生在单机或网络中不同计算机的应用程序之间。开发者还可以定义定制的DDE数据格式进行应用程序之间特别目的IPC,它们有更紧密耦合的通信要求。
大多数基于Windows的应用程序都支持DDE。
八、对象连接与嵌入
应用程序利用对象连接与嵌入(OLE)技术管理复合文档(由多种数据格式组成的文档),OLE提供使某应用程序更容易调用其它应用程序进行数据编辑的服 务。
例如,OLE支持的字处理器可以嵌套电子表格,当用户要编辑电子表格时OLE库可自动启动电子表格编辑器。当用户退出电子表格编辑器时,
该表格已在原 始字处理器文档中得到更新。在这里电子表格编辑器变成了字处理器的扩展,而如果使用DDE,用户要显式地启动电子表格编辑器。
同DDE技术相同,大多数基于Windows的应用程序都支持OLE技术。
九、动态连接库
Win32动态连接库(DLL)中的全局数据可以被调用DLL的所有进程共享,这就又给进程间通信开辟了一条新的途径,当然访问时要注意同步问题。
虽然可以通过DLL进行进程间数据共享,但从数据安全的角度考虑,不提倡这种方法,使用带有访问权限控制的共享内存的方法更好一些。
十、远程过程调用
Win32 API提供的远程过程调用(RPC)使应用程序可以使用远程调用函数,这使在网络上用RPC进行进程通信就像函数调用那样简单。
RPC既可以在单机不同进程间使用也可以在网络中使用。
由于Win32 API提供的RPC服从OSF-DCE (Open Software Foundation Distributed Computing Environment)标准。
所以通过 Win32 API编写的RPC应用程序能与其它操作系统上支持DEC的RPC应用程序通信。使用RPC开发者可以建立高性能、紧密耦合的分布式应用程 序。