1. 程式人生 > >Windows網路程式設計基礎(1)---郵槽

Windows網路程式設計基礎(1)---郵槽

/*
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進行測試