/*
2018-9-6 12:21:04
邮槽的使用
*/
预备知识:CreateFile,ReadFile的使用
关键的函数 CreateMailslot 如果建立失败 返回一个无效的句柄值INVILID_HANDLE_VALUE
用一个有效的句柄创建了邮槽之后,便可开始数据的实际读取。服务器是唯一能从邮槽
读入数据的进程
单项的 单线的数据传输
若想实现一个邮槽,要求开发一个服务器应用,来负责邮槽的创建。下述步骤解释了如
何编写一个基本的服务器应用:
1) 用CreateMailslot API函数创建一个邮槽句柄。
2) 调用ReadFile API函数,并使用现成的邮槽句柄,从任何客户端接收数据。
3) 用CloseHandle这个API函数,关闭邮槽句柄。
可以看出,要开发一个邮槽服务器程序,只需使用极少的 API调用。服务器进程是用
CreateMailslot这个API调用来创建邮槽的。定义如下
函数原型:
HANDLE CreateMailslot(
LPCTSTR lpName, //邮槽的名字
DWORD nMaxMessageSize, //收到消息的长度设置,设置为0时表示可以接受任意长度的数据
DWORD lReadTimeout, //0 或者 MAILSLOT_WAIT_FOREVER 读取时间
LPSECURITY_ATTRIBUTES lpSecurityAttributes // inheritance option;
}
服务端代码:
// MailSlot.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <windows.h>
#include <string>
int main()
{
//std::cout << "Hello World!\n";
const TCHAR *lpszSlotName = L"\\\\.\\Mailslot\\sample_JamesWu9527mailslot";
HANDLE mailslot = CreateMailslot(lpszSlotName, 0, MAILSLOT_WAIT_FOREVER, NULL);
if (INVALID_HANDLE_VALUE == mailslot)
{
std::cout << "CreateMailSlot Error : " << GetLastError() << std::endl;
return EXIT_FAILURE;
}
char strshowResult[256] = { 0 };
DWORD Numberofbyteread;
//发送数据
while (0 != ReadFile(mailslot, strshowResult, 256, &Numberofbyteread, NULL))
{
std::cout <<"Service: =>"<< Numberofbyteread << "bytes >>" << strshowResult << std::endl;
memcpy(strshowResult, "", Numberofbyteread);
Numberofbyteread = 0;
}
system("pause");
return EXIT_SUCCESS;
}
客户端
思想:
1) 使用CreateFile这个API函数,针对想向其传送数据的邮槽,打开指向它的一个引用句
柄。
2) 调用WriteFile这个API函数,向邮槽写入数据。
3) 完成了数据的写入后,用CloseHandle这个API函数,关闭打开的邮槽句柄。
Client1
#include <iostream>
#include <windows.h>
#include <string>
int main()
{
wchar_t Servername[] = L"\\\\.\\Mailslot\\sample_JamesWu9527mailslot";
HANDLE MailSlot = CreateFile(Servername, GENERIC_WRITE, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == MailSlot)
{
std::cout << "Please start up the service...\n";
std::cout << "Create File failed with Error Code: " << GetLastError() << std::endl;
system("pause");
return EXIT_FAILURE;
}
DWORD BytestWritten;
std::string strInput;
while (1)
{
std::cout << "Client1=>" << "Input you CMD: ";
std::cin >> strInput;
if ("exit" == strInput)
{
strInput = "The Client1 exited\n";
BOOL bflag = WriteFile(MailSlot, strInput.c_str(), strInput.length(), &BytestWritten, NULL);
if (FALSE == bflag)
{
std::cout << "Write file failed error " << GetLastError() << std::endl;
system("pause");
return EXIT_FAILURE;
}
break;
}
BOOL bflag = WriteFile(MailSlot, strInput.c_str(), strInput.length(), &BytestWritten, NULL);
if (FALSE == bflag)
{
std::cout << "Write file failed error " << GetLastError() << std::endl;
system("pause");
return EXIT_FAILURE;
}
strInput = "";
}
std::cout << "Wrote " << BytestWritten << " bytes\n";
CloseHandle(MailSlot);
system("pause");
return EXIT_SUCCESS;
}
服务端的一个升级版本
#include <iostream>
#include <windows.h>
#include <conio.h>
DWORD WINAPI ServerMialSlot(LPVOID lpPrameter);
void SendMessageToMainlSlot();
BOOL StopProcessing;
int main()
{
StopProcessing = FALSE;
DWORD ThreadId;
HANDLE MailSlot = CreateThread(NULL, 0, ServerMialSlot, NULL, 0, &ThreadId); //创建一个线程
std::cout << "Press a key to stop the server\n";
_getch();
//getchar();
StopProcessing = TRUE;
SendMessageToMainlSlot();
if (WaitForSingleObject(MailSlot, INFINITE) == WAIT_FAILED)
{
std::cout << "WaitForsingleobject failed with error " << GetLastError();
return EXIT_FAILURE;
}
system("pause");
return EXIT_SUCCESS;
}
DWORD __stdcall ServerMialSlot(LPVOID lpPrameter)
{
HANDLE mailslot = CreateMailslot(L"\\\\.\\Mailslot\\sample_mailslot", 2048, MAILSLOT_WAIT_FOREVER, NULL);
if (INVALID_HANDLE_VALUE == mailslot)
{
std::cout << "Failed to create a Mailslot the error code is: " << GetLastError();
return EXIT_FAILURE;
}
char buffer[2048];
DWORD numberofbyteRead;
DWORD Ret = ReadFile(mailslot, buffer, 2048, &numberofbyteRead, NULL);
while (Ret != 0)
{
if (StopProcessing)
break;
std::cout << "Received " << numberofbyteRead << " bytes\n";
}
CloseHandle(mailslot);
return EXIT_SUCCESS;
}
void SendMessageToMainlSlot()
{
HANDLE mailslot = CreateFile(L"\\\\.\\Mailslot\\sample_mailslot",
GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == mailslot)
{
std::cout << "Create FIle failed with the error code: " << GetLastError();
return;
}
DWORD byteswritten;
if (0 == WriteFile(mailslot, "STOP", 4, &byteswritten, NULL))
{
std::cout << "WriteFile failed with error code: " << GetLastError();
return;
}
CloseHandle(mailslot);
}
可以同上面的CLient进行测试