c++通道应用(处事器篇)
副标题#e#
【C++措施中定名管道通讯的实现】
最近进修c++中,试手进程选择实 现一个措施与被注入措施互通的东西,感受假如是计较机当地的通讯利用socket 好像有些不太理性,俗话说“杀鸡焉牛宰牛刀”,所以利用伟大的 google找到了更适合轻量级措施通讯的内容,即下面所要说的:“管道 ”。
首先凭据国际打点,先容下c++实现“管道” 的几 个焦点函数;
CreateNamedPipe( //处事器端建设 并定名一个管道,处事器端通过提供管道名与其举办通讯
LPCTSTR lpName, // 管道名称
DWORD dwOpenMode, // 管道打开模式
DWORD dwPipeMode, // 管道的其他模式界说
DWORD nMaxInstances, // 这个管道可以或许建设的最大实例数量 。必需是1到常数PIPE_UNLIMITED_INSTANCES间的一个值。它对付管道的所有实 例来说都应是沟通的
DWORD nOutBufferSize, // 发起的输出缓冲区长度;零暗示 用默认配置
DWORD nInBufferSize, // 发起的输入缓冲区长度;零暗示 用默认配置
DWORD nDefaultTimeOut, // 管道的默认期待超时。对一个管 道的所有实例来说都应沟通
LPSECURITY_ATTRIBUTES lpSecurityAttributes // pointer to security attributes
)
具体参数请见:http: //vbworld.sxnw.gov.cn/vbapi/detail/CreateNamedPipe.htm
C onnectNamedPipe( //指示一台处事器期待下去,直至客户机同一个定名管道连 接
HANDLE handle, //管道的句柄
lpOverlapped OVERLAPPED //如设为NULL(通报 ByVal As Long),暗示将线程挂起,直到一个客户同管道毗连为止。不然就立 即返回;此时,如管道尚未毗连,客户同管道毗连时就会触发lpOverlapped布局 中的事件工具。随后,可用一个期待函数来监督毗连
)
具体参数请见:http: //vbworld.sxnw.gov.cn/vbapi/detail/ConnectNamedPipe.htm
WaitNamedPipe( //由一个客户历程挪用,等待一个管道酿成可 用状态
LPCTSTR lpNamedPipeName, //指定要毗连的管道名称
DWORD nTimeOut //超时设定
)
具体参数请见:http: //vbworld.sxnw.gov.cn/vbapi/detail/WaitNamedPipe.htm CreateFile(
LPCTSTR lpFileName, //指向文件名的指针,假如是写入到管 道傍边,则写入管道名
DWORD dwDesiredAccess, //会见模式(写/读)
DWORD dwShareMode, //共享模式
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向 安详属性的指针
DWORD dwCreationDisposition, //如何建设
DWORD dwFlagsAndAttributes, //文件属性
HANDLE hTemplateFile //用于复制文件句柄
)
具体参数请见:http://baike.baidu.com/view/1288759.htm
#p#副标题#e#
WriteFile( //用于向 管道中写入内容
HANDLE hFile, // 文件句柄,通过CreateFile建设的句柄
LPCVOID lpBuffer, // 数据缓存区指针
DWORD nNumberOfBytesToWrite, // 你要写的字节数
LPDWORD lpNumberOfBytesWritten, // 用于生存实际写 入字节数的存储区域的指针
LPOVERLAPPED lpOverlapped // OVERLAPPED布局体指针
)
具体参数请见:http://baike.baidu.com/view/1295782.htm ReadFile( //用于读取管道中以写入的信息
HANDLE hFile, //文件的句柄
LPVOID lpBuffer, //用于生存读入数据的一个缓冲区
DWORD nNumberOfBytesToRead, //要读入的字符数
LPDWORD lpNumberOfBytesRead, //指向实际读取字节数 的指针
LPOVERLAPPED lpOverlapped //如文件打开时指定了 FILE_FLAG_OVERLAPPED,那么必需,用这个参数引用一个非凡的布局。该布局定 义了一次异步读取操纵。不然,应将这个参数设为NULL
)
具体参数请见:http://baike.baidu.com/view/1336847.htm。行了,假设看这篇文章的同学都已经 了VS2005下MFC的建设和利用,下面的内容将开始实刀实枪的开始“管道之 旅”,利用MFC建设一个尺度的管道通讯措施。
【server部门:】
1、为了更好的节制我们的措施,第一步界说一个管道基类是个好的做法 ,在这里我们警惕一个例子,建设一个"CMyPipe.h"的头文件,代码 如下:
#pragma once
class CMyPipe //建设我们的通道基类,主要为了利便定位通道
{
public:
CMyPipe(); //建设一个结构函数;
CMyPipe(LPCTSTR lpctstr); //结构函数的重载;
~CMyPipe(); //一个析构函数;
protected:
HANDLE MyPipe; //建设一个HANDLE 变量,用于界说我们的通道 头
CString MyPipeName; //建设一个通道名;
};
2、界说一个基类CMyPipe的扩展类CPipeServer ,将其写入到一个新的头文件中,在这里我定名为pp.h,代码如下:
#p#分页标题#e#
#pragma once
#include "CMyPipe.h"
class CPipeServer:public CMyPipe //界说基类CMyPipe的扩展 类
{
public: //结构函数
CPipeServer();
CPipeServer(LPCTSTR lpPipeName); //结构函数重载
~CPipeServer(); //析构函数
CWnd* GethWndServer(); //界说一个获取窗口函数
CWnd* SethWndServer(CWnd *pWndServer); //界说配置窗口的 函数
bool ServerReplyInfo(CString StrReply); //界说建设通道反 馈信息的函数
bool ServerExit(); //处事器退出时利用
static UINT ServerReadProc(LPVOID lParam); //管道处事器 建设后的操纵,建设处事器可不是让他闲着。。。
void InitPipeServer(UINT InstanceCount);
void UnInitPipeServer(void);
CPipeServer *m_pPipeServer; //CPipeServer类动态数组(可实 现多个管道实例,提高管道处事器端负荷处理惩罚本领)
UINT m_InstanceCount; //管道实例个数
private:
CWnd* m_pWndServer; //界说将要写入的窗口类变量
CWinThread *m_pWinThread; //每次利用新线程挪用处事器时的 存储线程变量
CString m_StrReply; //吸收的信息存储变量
};
3、接下来我们将对之前界说的函数在项目中的 cpp文件中举办实例化,并做应用:
//3个CMyPipe基类的实例化
CMyPipe::CMyPipe()//直接界说管道名
{
MyPipeName=_T("\\\\.\\pipe\\snmp");
}
CMyPipe::CMyPipe(LPCTSTR lpPipeName) //管道名的重载
{
MyPipeName=lpPipeName;
}
::CMyPipe::~CMyPipe()
{
MyPipeName.Empty();
}
CPipeServer::CPipeServer():CMyPipe()
{
m_StrReply.Empty();
m_pWndServer=NULL;
}
CPipeServer::CPipeServer(LPCTSTR lpPipeName):CMyPipe (lpPipeName)
{
m_StrReply.Empty();
m_pWndServer=NULL;
}
CPipeServer::~CPipeServer()
{
m_StrReply.Empty();
m_pWndServer=NULL;
}
//因为涉及到了新建线程吸收管道信息,所以需要定位控件窗口
CWnd * CPipeServer::SethWndServer(CWnd *pWndServer)
{
return m_pWndServer=pWndServer;
}
CWnd* CPipeServer::GethWndServer()
{
return m_pWndServer;
}
//定位控件窗口
void CPipeServer::InitPipeServer(UINT InstanceCount)
{
m_pPipeServer=NULL;
m_InstanceCount=0;
m_pPipeServer=new CPipeServer[InstanceCount];
if(m_pPipeServer!=NULL)
m_InstanceCount=InstanceCount;
}
void CPipeServer::UnInitPipeServer(void)
{
if(m_pPipeServer!=NULL){
delete [] m_pPipeServer;
m_pPipeServer=NULL;
m_InstanceCount=0;
}
}
//界说建设通道反馈信息的函数
bool CPipeServer::ServerReplyInfo(CString StrReply)
{
bool IsSuc=false;
MyPipe=CreateNamedPipe(MyPipeName,
PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE|PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
256,
256,
NULL, //NMPWAIT_USE_DEFAULT_WAIT,
NULL);
if (MyPipe!=INVALID_HANDLE_VALUE)
{
m_StrReply=StrReply;
IsSuc=true;
m_pWinThread=AfxBeginThread(ServerReadProc,(LPVOID) this);
}
return IsSuc;
}
//界说建设通道反馈信息的函数
//界说处事器退出时的操纵
bool CPipeServer::ServerExit()
{
bool IsSuc=false;
HANDLE hFile;
TCHAR buffer[256];
DWORD dwNumberOfBytesWritten;
WaitNamedPipe(MyPipeName,NMPWAIT_WAIT_FOREVER);
hFile=CreateFile (MyPipeName,GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRIT E,
NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_ARCHIVE|FILE_FLAG_WRITE_THROUGH,NULL );
if(hFile==INVALID_HANDLE_VALUE)
{
return IsSuc;
}
_stprintf(buffer,_T("exit"));
if (WriteFile(hFile,buffer,(_tcslen(buffer)+1)*sizeof (TCHAR),&dwNumberOfBytesWritten,NULL))
{
IsSuc=true;
}
CloseHandle(hFile);
return IsSuc;
}
//界说处事器退出时的操纵
//处事器读取并处理惩罚信息
UINT CPipeServer::ServerReadProc(LPVOID lParam)
{
CPipeServer * pPipeServer=(CPipeServer*)lParam;
DWORD dwNumberOfBytesRead,dwNumberOfBytesWritten;
TCHAR buffer[256];
while(ConnectNamedPipe(pPipeServer->MyPipe,NULL))
{
while(ReadFile(pPipeServer- >MyPipe,buffer,256*sizeof(TCHAR),&dwNumberOfBytesRead,NULL))
{
if(dwNumberOfBytesRead==0) break;
if(_tcscmp(buffer,_T("exit"))==0)
{
DisconnectNamedPipe(pPipeServer->MyPipe);
CloseHandle(pPipeServer- >MyPipe);
return 0;
}
if(pPipeServer->m_pWndServer!=NULL)
{
((CListBox*)pPipeServer->m_pWndServer- >GetDlgItem(IDC_LBCONTENT))->InsertString(0,buffer);
}
_tcscpy(buffer,pPipeServer->m_StrReply);
WriteFile(pPipeServer->MyPipe,buffer,(_tcslen (buffer)+1)*sizeof(TCHAR),&dwNumberOfBytesWritten,NULL);
}
DisconnectNamedPipe(pPipeServer->MyPipe); //管道处事 器断开该实例的毗连
}
CloseHandle(pPipeServer->MyPipe); //封锁实例句柄
return 0;
}
//处事器读取并处理惩罚信息
//利用一个ID为IDC_BTNCONNECT的Button控件节制处事器开启/关 闭,并利用一个ID为IDC_BTNCONNECT的combo box的控件显示处事器端显示的信 息。
void CaccDlg::OnBnClickedBtnconnect()
{
CPipeServer * pPipeServer=(CPipeServer*)this;
CString MyCaption;
GetDlgItem(IDC_BTNCONNECT)->GetWindowText (MyCaption);
UINT i;
if(MyCaption.Compare(_T("毗连"))==0) {
for(i=0;i<pPipeServer- >m_InstanceCount;i++){
pPipeServer->m_pPipeServer->SethWndServer (this);
pPipeServer->m_pPipeServer- >ServerReplyInfo(_T("处事器应答!"));
}
GetDlgItem(IDC_BTNCONNECT)- >SetWindowText(_T("断开"));
}
else{
for(i=0;i<pPipeServer- >m_InstanceCount;i++)
pPipeServer->m_pPipeServer- >ServerExit();
GetDlgItem(IDC_BTNCONNECT)- >SetWindowText(_T("毗连"));
}
}
OK,按F5执行试一下……
是 不是有句提示:“CaccDlg”: 不是类或定名空间名称
哈哈 ,说明你照抄了上面的那段OnBnClickedBtnconnect()的代码,请把 “CaccDlg”改成你所建造的项目标Dlg名。