免费预览已结束,剩余10页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C+与C#进程通信案例附源码最新C+与C#进程通信案例源码,欢迎在线学习c+ 教程.“命名管道”是一种简单的进程间通信(IPC)机制。命名管道可在同一台计算机的不同进程之间,或在跨越一个网络的不同计算机的不同进程之间,支持可靠的、单向或双向的数据通信。用命名管道来设计应用程序实际非常简单,并不需要事先深入掌握基层网络传送协议(如TCP/IP或IPX)的知识。因为命名管道利用了微软网络提供者(MSNP)重定向器,通过一个网络,在各进程间建立通信。这样一来,应用程序便不必关心网络协议的细节。命令管道是围绕Windows文件系统设计的一种机制,采用“命名管道文件系统”(NamedPipeFileSystem,NPFS)接口。因此,客户机和服务器应用可利用标准的Win32文件系统API函数(如ReadFile和WriteFile)来进行数据的收发。通过这些API函数,应用程序便可直接利用Win32文件系统命名规范,以及WindowsNT/Windows2000文件系统的安全机制。NPFS依赖于MSNP重定向器在网上进行命名管道数据的发送和接收。这样一来,便可实现接口的“与协议无关”特性:若在自己开发的应用程序中使用命名管道在网上不同的进程间建立通信,程序员不必关心基层网络传送协议(如TCP和IPX等等)的细节。客户机和服务器命名管道最大的特点便是建立一个简单的客户机服务器程序设计体系。在这个体系结构中,在客户机与服务器之间,数据既可单向传递,亦可双向流动。对命名管道 服务器和客户机来说,两者的区别在于:服务器是唯一一个有权创建命名管道的进程,也只有它才能接受管道客户机的连接请求。对一个客户机应用来说,它只能同 一个现成的命名管道服务器建立连接。在客户机应用和服务器应用之间,一旦建好连接,两个进程都能对标准的Win32函数,在管道上进行数据的读取与写入。这些函数包括ReadFile和WriteFile等等。服务器要想实现一个命名管道服务器,要求必须开发一个应用程序,通过它创建命名管道的一个或多个“实例”,再由客户机进行访问。对服务器来说,管道实例实际就是一个句柄,用于从本地或远程客户机应用接受一个连接请求。按下述步骤行事,便可写出一个最基本的服务器应用:1)使用API函数CreateNamedPipe,创建一个命名管道实例句柄。2)使用API函数ConnectNamedPipe,在命名管道实例上监听客户机连接请求。3)使用API函数ReadFile,从客户机接收数据;使用API函数WriteFile,将数据发给客户机。4)使用API函数DisconnectNamedPipe,关闭命名管道连接。5)使用API函数CloseHandle,关闭命名管道实例句柄。首先,我们的服务器进程需要使用CreateNamedPipe这个API调用,创建一个命名管道实例。下面给出CreateNamedPipe()的函数原型:HANDLE CreateNamedPipe(LPCTSTR lpName, /指向管道名称的指针 DWORD dwOpenMode, /管道打开模式 DWORD dwPipeMode, /管道模式 DWORD nMaxInstances, /最大实例数 DWORD nOutBufferSize, /输出缓存大小 DWORD nInBufferSize, /输入缓存大小 DWORD nDefaultTimeOut,/超时设置 LPSECURITY_ATTRIBUTES lpSecurityAttributes /安全属性指针 ); 其中几个主要参数如下:lpName是管道的名称,命名管道的命名采用如下格式:ServerNamePipePipeName其中,第一部分ServerName指定了服务器的名字,命名管道服务即在此服务器创建,而且要由它对进入的连接请求进行“监听”,其字串部分可表示为一个小数点”.”(表示本机)、星号(当前网络字段)、域名或是一个真正的服务;第二部分Pipe是一个不可变化的硬编码字串,以指出该文件是从属于NPFS,不区分大小写;第三部分PipeName则是应用程序可以唯一定义及标识一个命名管道的名字,而且可以设置多级目录。dwOpenMode参数用于指示一个管道创建好之后,它的传输方向、I/O控制以及安全模式。PIPE_ACCESS_标志决定了在客户机与服务器之间,数据在管道上的流动方向。可用PIPE _ACCESS_DUPLEX标志以双向传输方式打开一个管道。也就是说,在客户机与服务器之间,数据可以双向传输。除此以外,亦可使用PIPE_ACCESS_INBOUND或者PIPE_ACCESS_OUTBOUND标志,以单向传输方式打开一个管道。也就是说,数据只能从客户机传向服务器,或从服务器传向客户机。dwPipeMod命名管道提供了两种基本的通信模式:字节模式(PIPE_TYPE_BYTE)和消息模式(PIPE_TYPE_MESSAGE)。 在字节模式中,信息以连续字节流的形式在客户与服务器之间流动,这也就意味着,对于客户机应用和服务器应用,在任何一个特定的时间段内,都无法准确知道有 多少字节从管道中读出或写入。在这种通信模式中,一方在向管道写入某个数量的字节后,并不能保证管道另一方能读出等量的字节。对于消息模式,客户机和服务 器则是通过一系列不连续的数据包进行数据的收发。从管道发出的每一条消息都必须作为一条完整的消息读入。其他的函数及其参数含义详见msdn,此处不一一讲解。服务器调用该函数,如果在已定义超时值变为零以前,有一个实例管道可以使用,则创建成功并返回管道句柄,以此侦听来自客户机的连接请求。客户机实现一个命名管道客户机时,要求开发一个应用程序,令其建立与某个命名管道服务器的连接。注意客户机不可创建命名管道实例。然而,客户机可打开来自服务器的、现成的实例。下述步骤讲解了如何编写一个基本的客户机应用:1)用API函数WaitNamedPipe,等候一个命名管道实例可供自己使用。2)用API函数CreateFile,建立与命名管道的连接。3)用API函数WriteFile和ReadFile,分别向服务器发送数据,或从中接收数据。4)用API函数CloseHandle,关闭打开的命名管道会话。建立一个连接之前,客户机需要用WaitNamedPipe函数,检查是否存在一个现成的命名管道实例。WaitNamedPipe成功完成后,客户机需要用CreateFile这个API函数,打开指向服务器命名管道实例的一个句柄。简单说来,服务器调用CreateNamedPipe来创建管道,如果在已定义超时值变为零以前,有一个实例管道可以使用,则创建成功并返回管道句柄,以此侦听来自客户机的连接请求。另一方面,客户机通过函数WaitNamedPipe()使服务器进程等待来自客户的实例连接。如果在超时值变为零以前,有一个管道可供连接使用,则函数将成功返回,并通过调用CreateFile()或CallNamedPipe()来呼叫对服务器的连接。此时服务器将接受客户的连接请求,成功建立连接,服务器调用的等待客户机建立连接的ConnectNamedPipe()函数也将成功返回。然后,管道两端就可以进行通信了。从调用时序上看,首先是客户机通过WaitNamedPipe()使服务器的CreateFile()在限时时间内创建实例成功,然后双方通过ConnectNamedPipe()和CreateFile()成功连接,在返回用以通信的文件句柄后,客户、服务双方即可进行通信。在建立了连接后,客户机与服务器即可通过ReadFile()和WriteFile()并利用得到的管道句柄,以文件读写的形式彼此间进行信息交换。当客户与服务器的通信结束,或是由于某种原因一方需要断开时,由客户机调用CloseFile()函数关闭打开的管道句柄,服务器随即调用DisconnectNamedPipe()函数。当然,服务器也可以通过单方面调用DisconnectNamedPipe()来终止连接。在终止连接后调用函数CloseHandle()来关闭此管道。下篇将给出的程序清单即是按照上述方法实现的命名管道服务器和客户机进行通信的程序实现代码我采用的是C#开发的一个windows应用程序(pipe_server_csharp)作为服务器端,而MFC开发的应用程序(NamedPipeClient_vc)作为客户端。客户端和服务器端要进行频繁的大量的通信,常见的是文本信息和曲线数据,例如,一共有10条曲线,每条曲线有1000000条double数据。服务器端:服务器端是用在VS2005中用C#开发的一个名为pipe_server_csharp的应用程序,只有一个名为frmServer的主界面。由于管道的相关API函数都是属于kernel32.dll函数,C#中不能直接调用,所以必须将所要用到的API函数全部封装在一个类NamedPipeNative中。 至于如何调用这些API函数,有兴趣的朋友可以上网搜索,或者看我的另一篇文章C#中怎么调用命名管道的WinAPI。NamedPipeNative类中几个主要函数如下(大家可以对比这些重写的API函数和原来的函数有什么变化):DllImport(kernel32.dll, SetLastError=true)public static extern IntPtr CreateNamedPipe(String lpName, / pipe nameuint dwOpenMode, / pipe open modeuint dwPipeMode,/ pipe-specific modesuint nMaxInstances,/ maximum number of instancesuint nOutBufferSize,/ output buffer sizeuint nInBufferSize,/ input buffer sizeuint nDefaultTimeOut,/ time-out intervalIntPtr pipeSecurityDescriptor/ SD);DllImport(kernel32.dll, SetLastError=true)public static extern bool ConnectNamedPipe(IntPtr hHandle,/ handle to named pipeOverlapped lpOverlapped/ overlapped structure);DllImport(kernel32.dll, SetLastError=true)public static extern IntPtr CreateFile(String lpFileName,/ file nameuint dwDesiredAccess,/ access modeuint dwShareMode,/ share modeSecurityAttributes attr,/ SDuint dwCreationDisposition,/ how to createuint dwFlagsAndAttributes,/ file attributesuint hTemplateFile / handle to template file); DllImport(kernel32.dll, SetLastError=true)public static extern bool ReadFile(IntPtr hHandle, / handle to filebyte lpBuffer,/ data buffer字节流uint nNumberOfBytesToRead,/ number of bytes to readbyte lpNumberOfBytesRead,/ number of bytes readuint lpOverlapped/ overlapped buffer);DllImport(kernel32.dll, SetLastError=true)public static extern bool WriteFile(IntPtr hHandle, / handle to filebyte lpBuffer,/ data buffer字节流uint nNumberOfBytesToWrite, / number of bytes to writebyte lpNumberOfBytesWritten, / number of bytes writtenuint lpOverlapped / overlapped buffer);还有其他一些常量:public const uint PIPE_ACCESS_DUPLEX = 0x00000003;public const uint PIPE_ACCESS_OUTBOUND = 0x00000002;public const uint PIPE_TYPE_BYTE = 0x00000000;public const uint PIPE_TYPE_MESSAGE = 0x00000004;在此不一一列举了。封装之后,在C#中就可以直接调用这些函数和常量了。另外,创建了一个类CMyPipe,封装了服务器管道的属性和方法,如创建管道,读写数据等:namespace pipe_server_csharp public class CMyPipe private string m_PipeName;/管道名全称 public string PipeName get return m_PipeName; set m_PipeName = value; private IntPtr m_HPipe;/管道句柄 public IntPtr HPipe get return m_HPipe; set m_HPipe = value; public CMyPipe()/无参构造函数 m_HPipe = (IntPtr)NamedPipeNative.INVALID_HANDLE_VALUE; m_PipeName = .piperobinTest; public CMyPipe(string pipeName)/有参构造函数 m_HPipe = (IntPtr)NamedPipeNative.INVALID_HANDLE_VALUE; m_PipeName = pipeName; CMyPipe()/析构函数 Dispose(); public void Dispose() lock (this) if (m_HPipe != (IntPtr)NamedPipeNative.INVALID_HANDLE_VALUE) NamedPipeNative.CloseHandle(m_HPipe); m_HPipe = (IntPtr)NamedPipeNative.INVALID_HANDLE_VALUE; public void CreatePipe()/创建管道 m_HPipe = NamedPipeNative.CreateNamedPipe(m_PipeName, NamedPipeNative.PIPE_ACCESS_DUPLEX, / 数据双工通信 NamedPipeNative. PIPE_TYPE_MESSAGE | NamedPipeNative.PIPE_WAIT,100, / 最大实例个数 128, / 流出数据缓冲大小 128, / 流入数据缓冲大小 150, / 超时,毫秒 IntPtr.Zero / 安全信息 ); if (m_HPipe.ToInt32() = NamedPipeNative.INVALID_HANDLE_VALUE) frmServer.ActivityRef.AppendText(创建命名管道失败 ); frmServer.ActivityRef.AppendText(Environment.NewLine); return; frmServer.ActivityRef.AppendText(创建命名管道完毕 ); frmServer.ActivityRef.AppendText(Environment.NewLine); public void ReadCurveData()/读取曲线数据 int nCurvesToRead = 0; nCurvesToRead = ReadInt(HPipe);/先读取需要读取的曲线条数,如 frmServer.CurveDataList.Clear(); for (int j = 1; j = nCurvesToRead; j+) string curveName = ReadString(HPipe);/读取该曲线名称 int nCount = 0; nCount = ReadInt(HPipe);/读取该曲线的数据总数(数组大小) double readData = new doublenCount; for (int i = 0; i m_hThread,0) if(m_pThread) delete m_pThread; m_pThread = NULL; /客户端和服务器端建立连接void CMyPipe:ClientCreateFile() BOOL ret = :WaitNamedPipe(FullPipeName, 5000); if (!ret) /ClientMsg=管道忙或者没有启动n; return; m_hPipe = :CreateFile(FullPipeName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (m_hPipe = INVALID_HANDLE_VALUE) char szErr256 = ; DWORD dwErr = GetLastError(); sprintf(szErr, %l, dwErr); /ClientMsg=szErr; return; /ClientMsg=打开管道了n;/写字符串void CMyPipe:WriteString(char *szMsg) DWORD dwSize = strlen(szMsg)+1, dwBytesWritten = 0; BOOL ret =WriteFile(m_hPipe, &dwSize, 4, &dwBytesWritten, NULL); if (ret) BOOL ret2=WriteFile(m_hPipe, szMsg, dwSize, &dwBytesWritten, NULL); /写单精度void CMyPipe:WriteFloat(float szMsg) DWORD dwSize = 4, dwBytesWritten = 0; BOOL ret=WriteFile(m_hPipe, &szMsg, dwSize, &dwBytesWritten, NULL);/写双精度void CMyPipe:WriteDouble(double szMsg) DWORD dwSize = 8, dwBytesWritten = 0; BOOL ret=WriteFile(m_hPipe, &szMsg, dwSize, &dwBytesWritten, NULL);/写整型void CMyPipe:WriteInt(int szMsg) DWORD dwSize = 4, dwBytesWritten = 0; BOOL ret=WriteFile(m_hPipe, &szMsg, dwSize, &dwBytesWritten, NULL);void CMyPipe:ClosePipe() CloseHandle(m_hPipe);/读字符串char * CMyPipe:ReadString() char *readStr; DWORD drSize=0, dwBytesRead = 0; BOOL ret =ReadFile(m_hPipe, &drSize, 4, &dwBytesRead, NULL); if (ret) readStr=new chardrSize; BOOL ret2=ReadFile(m_hPipe, readStr, drSize, &dwBytesRead, NULL); return readStr;int CMyPipe:ReadInt() int intRead=0; DWORD drSize=4, dwBytesRead = 0; BOOL ret =ReadFile(m_hPipe, &intRead, drSize, &dwBytesRead, NULL); return intRead;float CMyPipe:ReadFloat() float floatRead=0; DWORD drSize=4, dwBytesRead = 0; BOOL ret =ReadFile(m_hPipe, &floatRead, drSize, &dwBytesRead, NULL); return floatRead;double CMyPipe:ReadDouble() double floatRead=0; DWORD drSize=8, dwBytesRead = 0; BOOL ret =ReadFile(m_hPipe, &floatRead, drSize, &dwBytesRead, NULL); return floatRead;而主程序NamedPipeClient_vcDlg.cpp如下:CMyPipe thePipe;/连接服务器管道void CNamedPipeClient_vcDlg:OnOpen() / TODO: Add your control notification handler code here thePipe.ClientCreateFile();/发送数据void CNamedPipeClient_v
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 通信基站冬季基础施工方案
- 智慧工地建设技术方案
- 雨水管网改造项目工程勘察方案
- 装配式建筑产业基地建设项目竣工验收报告
- 雨水管网改造项目
- 装饰装修工程竣工验收报告
- 注塑车间设备点检管理制度
- 园林绿化验收管理制度
- 数字化教学在小学数学课堂中的应用研究
- 有色金属精深加工项目水土保持方案报告
- 新版2026年新教材统编版九年级上册道德与法治期末复习全册考点提纲
- 羊绒衫制作工安全操作规程
- 新版2026秋新苏教版小学科学五年级上册全册知识点考点合集
- 2027兴业银行校园招聘笔试参考题库及答案详解
- ASME B31.3-2024 中文版(工艺管道规范 引用 ASME V 卷无损检测要求)
- 武汉产业投资控股集团有限公司招聘笔试参考题库及答案详解
- 2026年海南发展控股公司招聘试题及答案
- 2025年山东公务员考试行测真题完整版(含答案+详细解析)
- 肿瘤类器官模型应用
- 《JBT 20114.4-2009 糖浆剂瓶封口机》专题研究报告
- 喷涂工序低温烘干控制规范
评论
0/150
提交评论