window API一天一练之邮槽

邮槽通信的进程分为服务端和客户端.服务端创建邮槽,客户端通过邮槽名打开邮槽,获得句柄后可以向邮槽写数据. 邮槽通信是单向通信,只能由客户端向服务端发送数据.下面来看看有关邮槽的几个API

HANDLE WINAPICreateMailslot(

 _In_      LPCTSTR lpName,

  _In_      DWORDnMaxMessageSize,

  _In_      DWORDlReadTimeout,

  _In_opt_  LPSECURITY_ATTRIBUTESlpSecurityAttributes

);

功能:创建一个邮槽

参数:  lpName   指定的邮槽名,格式必须为  \\.\mailslot\[path]name

nMaxMessageSize  可以写到邮槽中的单个消息的最大字节数,如果为0则表示可以是任意大小的消息.

lReadTimeout    读取操作可以等待多久,0表示没有可读的消息则直接返回, MAILSLOT_WAIT_FOREVER表示一直等待可读消息.

lpSecurityAttributes  安全属性结构体指针,   可以为NULL

 

返回值: 如果成功,返回邮槽句柄,服务端通过句柄操作邮槽.如果失败则返回INVALID_HANDLE_VALUE

 

BOOL WINAPI GetMailslotInfo(
  _In_       HANDLE hMailslot,
  _Out_opt_  LPDWORD lpMaxMessageSize,
  _Out_opt_  LPDWORD lpNextSize,
  _Out_opt_  LPDWORD lpMessageCount,
  _Out_opt_  LPDWORD lpReadTimeout
);

功能:获取有关邮槽的信息

参数: hMailslot  邮槽句柄

lpMaxMessageSize     单个消息的最大字节数, 也可以为NULL

lpNextSize   下一个消息的大小,可以为NULL,为MAILSLOT_NO_MESSAGE表示没有下一个消息

lpMessageCount  等待读取的消息数, 可以为NULL,

lpReadTimeout   等待可读消息的时间, 也可以为NULL

 

返回值:成功返回非0,失败返回0

 

BOOL WINAPI SetMailslotInfo(
  _In_  HANDLE hMailslot,
  _In_  DWORD lReadTimeout
);
 

功能:设置等待可读消息的超时时间


服务端通过ReadFile从邮槽中读取数据,客户端通过CreateFile打开邮槽,WriteFile向邮槽写数据。以下是我用Qt做的简单验证程序,由于不熟悉window窗台程序,所以只能用Qt了。

客户端代码

MailSlotClient::MailSlotClient(QWidget *parent, Qt::WFlags flags)
	: QDialog(parent, flags)
{
	m_pMailSlotNameLbl = new QLabel(tr("MailSlot Name:"),this);
	m_pMailSlotNameLEdit = new QLineEdit(this);
	m_pMessageText = new QTextEdit(this);
	m_pMainLayout = new QGridLayout(this);
	m_pSendMessageBtn = new QPushButton(tr("Send Message "),this);
	this->setLayout(m_pMainLayout);
	m_pMainLayout->addWidget(m_pMailSlotNameLbl,0,0,1,1);
	m_pMainLayout->addWidget(m_pMailSlotNameLEdit,0,1,1,1);
	m_pMainLayout->addWidget(m_pSendMessageBtn,0,2,1,1);
	m_pMainLayout->addWidget(m_pMessageText,1,0,4,4);
	connect(m_pSendMessageBtn,SIGNAL(clicked()),this,SLOT(SendMessageSlot()));
	//ui.setupUi(this);
}

MailSlotClient::~MailSlotClient()
{

}

void MailSlotClient::SendMessageSlot()
{
	QString name = m_pMailSlotNameLEdit->text();
	string szMailSlotName = (string("\\\\.\\mailslot\\") + name.toStdString()).c_str();
	//LPSTR szMailSlotName = "\\\\.\\mailslot\\simplemailslot";
	HANDLE hFile ;
	hFile = CreateFile(szMailSlotName.c_str(),GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		QMessageBox::information(this,tr("提示"),tr("打开邮槽失败!"),QMessageBox::Ok);
		return ;
	}
	DWORD dwWriteSize;
	string message = m_pMessageText->toPlainText().toStdString();
	WriteFile(hFile,message.c_str(),message.size(),&dwWriteSize,NULL);
	CloseHandle(hFile);
}

服务端代码:

MailSlotServer::MailSlotServer(QWidget *parent, Qt::WFlags flags)
	: QDialog(parent, flags)
{
	m_pMailSlotNameLbl = new QLabel(tr("MailSlot Name:"),this);
	m_pMailSlotNameLEdit = new QLineEdit(this);
	m_pMessageText = new QTextEdit(this);
	m_pMainLayout = new QGridLayout(this);
	m_pCreateMailSlotBtn = new QPushButton(tr("Create MailSlot "),this);
	this->setLayout(m_pMainLayout);
	m_pMainLayout->addWidget(m_pMailSlotNameLbl,0,0,1,1);
	m_pMainLayout->addWidget(m_pMailSlotNameLEdit,0,1,1,1);
	m_pMainLayout->addWidget(m_pCreateMailSlotBtn,0,2,1,1);
	m_pMainLayout->addWidget(m_pMessageText,1,0,4,4);
	connect(m_pCreateMailSlotBtn,SIGNAL(clicked()),this,SLOT(CreateMailSlot()));
}

MailSlotServer::~MailSlotServer()
{

}



void MailSlotServer::CreateMailSlot()
{
	HANDLE hMailSlot;
	QString name = m_pMailSlotNameLEdit->text();
	string szMailSlotName = (string("\\\\.\\mailslot\\") + name.toStdString()).c_str();
	hMailSlot = CreateMailslot(szMailSlotName.c_str() ,0,MAILSLOT_WAIT_FOREVER,NULL);

	if (hMailSlot == INVALID_HANDLE_VALUE)
	{
		QMessageBox::information(this,tr("提示"),tr("创建邮槽失败!"),QMessageBox::Ok);
		return ;
	}

	DWORD dwMessageCount = 0;
	DWORD dwMessageSize = 0;
	DWORD dwReadSize = 0;
	bool bFinish =false;
	while (TRUE)
	{
		BOOL bResult = GetMailslotInfo(hMailSlot,NULL,&dwMessageSize,&dwMessageCount,NULL);
		if (!bResult)
		{
			QMessageBox::information(this,tr("提示"),tr("获取邮槽信息失败!"),QMessageBox::Ok);
			return ;
		} 
			while (dwMessageCount != 0)
			{
				char *lpBuffer = new char[dwMessageSize];
				memset(lpBuffer,0,dwMessageSize);
				ReadFile(hMailSlot,lpBuffer,dwMessageSize,&dwReadSize,NULL);
				
				m_pMessageText->setText(QString::fromStdString(lpBuffer));
				GetMailslotInfo(hMailSlot,NULL,&dwMessageSize,&dwMessageCount,NULL);
				bFinish = true;    
			}
		if (bFinish)   //读取完了就返回,不然一直卡住就没法显示接收到的数据了

		{
			return;
		}
	}
}

先启动服务端,输入邮槽名,创建邮槽,程序循环等待客户端发来数据。接收到数据后显示。再启动客户端,输入邮槽名,输入要发送的数据,点击发送,数据将显示在服务端。



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows C++ 中,可以使用邮槽(Named Pipe)实现进程间通信。下面是一个简单的示例,演示如何创建一个邮槽并向其写入信息: ```cpp #include <windows.h> #include <iostream> int main() { HANDLE hPipe; DWORD dwWritten; // 创建邮槽 hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\MyPipe"), PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, // 最大实例数 0, // 输出缓冲区大小 0, // 输入缓冲区大小 NMPWAIT_USE_DEFAULT_WAIT, NULL); if (hPipe == INVALID_HANDLE_VALUE) { std::cout << "创建邮槽失败!" << std::endl; return 1; } // 等待客户端连接 if (!ConnectNamedPipe(hPipe, NULL)) { std::cout << "客户端连接失败!" << std::endl; CloseHandle(hPipe); return 1; } // 向邮槽写入信息 const char* msg = "Hello, World!"; if (!WriteFile(hPipe, msg, strlen(msg) + 1, &dwWritten, NULL)) { std::cout << "写入信息失败!" << std::endl; CloseHandle(hPipe); return 1; } std::cout << "已向邮槽写入信息:" << msg << std::endl; // 关闭邮槽 CloseHandle(hPipe); return 0; } ``` 在此示例中,我们通过调用 `CreateNamedPipe` 创建了一个名为 `\\.\pipe\MyPipe` 的邮槽,并指定了以下参数: - `PIPE_ACCESS_OUTBOUND`:邮槽只用于输出。 - `PIPE_TYPE_MESSAGE`:邮槽是消息类型的。 - `PIPE_READMODE_MESSAGE`:邮槽按消息处理。 - `PIPE_WAIT`:当客户端连接时,服务器应该等待。 然后,我们使用 `ConnectNamedPipe` 告诉操作系统等待客户端连接。一旦客户端连接,我们就可以使用 `WriteFile` 写入信息。 最后,我们关闭邮槽并返回。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值