邮槽通信的进程分为服务端和客户端.服务端创建邮槽,客户端通过邮槽名打开邮槽,获得句柄后可以向邮槽写数据. 邮槽通信是单向通信,只能由客户端向服务端发送数据.下面来看看有关邮槽的几个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;
}
}
}
先启动服务端,输入邮槽名,创建邮槽,程序循环等待客户端发来数据。接收到数据后显示。再启动客户端,输入邮槽名,输入要发送的数据,点击发送,数据将显示在服务端。