Windows網路程式設計基礎(1)---郵槽
阿新 • • 發佈:2018-11-17
/*
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進行測試