国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
郵槽
Microsoft Windows NT, Windows 2000, Window 95 和Windows 98----但不包括Windows CE----提供了一種簡單的單向的"進(jìn)程間通信"(interprocess communication, IPC)機(jī)制. 這個(gè)機(jī)制的名字非常古怪,叫做"郵槽(Mailslot).用最簡單的話來說,通過郵槽,客戶機(jī)進(jìn)程可將消息傳送或廣播給一個(gè)或多個(gè)服務(wù)器進(jìn)程.

1.郵槽實(shí)施細(xì)節(jié)

   郵槽是圍繞Windows文件系統(tǒng)接口設(shè)計(jì)出來的.客戶機(jī)和服務(wù)器應(yīng)用需要使用標(biāo)準(zhǔn)的Win32文件系統(tǒng)I/O(輸入/輸出)函數(shù),比如ReadFile和WriteFile等等,以便在郵槽上收發(fā)數(shù)據(jù),同時(shí)利用Win32文件系統(tǒng)的命名規(guī)則.郵槽必須依賴Windows重定向器,通過一個(gè)"郵槽文件系統(tǒng)"(Mailslot File System ,   MSFS), 來創(chuàng)建及標(biāo)識(shí)郵槽.

1.1 郵槽的名字

      對(duì)郵槽進(jìn)行標(biāo)識(shí)時(shí),需遵守下述命名規(guī)則:

      \\server\Mailslot\[path]name

     請(qǐng)將上述字串分為三段來看: \\server, \Mailslot和\[path]name.第一部分\\server對(duì)應(yīng)于服務(wù)器的名字,我們要在上面創(chuàng)建郵槽,并在上面運(yùn)行服務(wù)器程序.第二部分\Mailslot是一個(gè)"硬編碼"的固定字串,用于告訴系統(tǒng)這個(gè)文件名從屬于MSFS.而第三部分\[path]name則允許應(yīng)用程序獨(dú)一無二地定義及標(biāo)識(shí)一個(gè)郵槽名.其中,"path"代表路徑,可指定多級(jí)目錄.舉個(gè)例子來說,對(duì)一個(gè)郵槽進(jìn)行標(biāo)識(shí)時(shí),下面這些形式的名字都是合法的(注意Mailslot不得變化,必須原文照輸).

     \\Oreo\Mailslot\Mymailslot

1.2 消息的長度

   郵槽通常用"數(shù)據(jù)報(bào)"(Datagram)在網(wǎng)絡(luò)上傳遞消息.數(shù)據(jù)報(bào)實(shí)際是一些小數(shù)據(jù)包,只不過要以"無連接"的形式,通過網(wǎng)絡(luò)進(jìn)行傳輸."無連接"意味著每個(gè)數(shù)據(jù)包在發(fā)給接收者之后,不要求對(duì)方提供包的收到確認(rèn)信息.顯然,這是一種"不可靠"的數(shù)據(jù)傳輸,因?yàn)闊o法保證消息肯定能正確送達(dá).然而,通過無連接傳輸,我們確實(shí)可將消息從一個(gè)客戶機(jī)廣播給多個(gè)服務(wù)器.當(dāng)然,上述情況也有例外.在Windows NT 和Windows2000中,假如消息的長度超過424個(gè)字節(jié).

   若消息長度超過426字節(jié),便必須在一個(gè)SMB會(huì)話之上,通過一種"面向連接"的協(xié)議進(jìn)行傳輸,而不再采用無連接的"數(shù)據(jù)報(bào)"形式.這樣一來,在消息較大的情況下,便可保證它們的穩(wěn)定,高效傳輸.然而,此時(shí)再也不能將一條消息從客戶機(jī)廣播給多個(gè)服務(wù)器.對(duì)于"面向連接"的傳輸來說,它必然是一種"一對(duì)一"通信:一個(gè)客戶對(duì)一個(gè)服務(wù)器,在不同的進(jìn)程之間,使用"面向連接"的傳輸方式,往往可保證數(shù)據(jù)傳輸?shù)目煽啃?

1.3 應(yīng)用程序的編譯

    用Microsoft VisualC++編制一個(gè)郵槽客戶機(jī)或服務(wù)器應(yīng)用程序時(shí),必須在程序文件中將Winbase.h這個(gè)包容文件包括在內(nèi).假如已經(jīng)包含了Windows.h(大多數(shù)應(yīng)用程序都會(huì)這樣), 那么也可將Winbase.h省去.此外,應(yīng)用程序也要負(fù)責(zé)建立與Kernel32.lib的鏈接,這通常需要用VisualC++鏈接器標(biāo)志進(jìn)行配置.

 1.4錯(cuò)誤代碼

    開發(fā)郵槽客戶機(jī)和服務(wù)器應(yīng)用時(shí),所有Win32API函數(shù)(CreateFile和CreateMailslot除外)在調(diào)用失敗的情況下,都會(huì)返回0值.CreateFile和CreateMailslot這兩個(gè)API卻會(huì)返回INVALID_HANDLE_VALUE(無效句柄值)。若這些API函數(shù)調(diào)用失敗,應(yīng)用程序即應(yīng)調(diào)用GetLastError函數(shù),來接收與此次失敗有關(guān)的特殊信息。至于所有錯(cuò)誤代碼的一個(gè)完整列,可參考Winerror.h

2. 基本客戶機(jī)/服務(wù)器

   郵槽建立了一個(gè)簡單的客戶機(jī)/服務(wù)器設(shè)計(jì)體系。在這個(gè)體系中,數(shù)據(jù)只能從客戶機(jī)傳到服務(wù)器,數(shù)據(jù)通信是單向進(jìn)行的。服務(wù)器進(jìn)程的職責(zé)是創(chuàng)建一個(gè)郵槽,而且是能從郵槽讀取數(shù)據(jù)的唯一一個(gè)進(jìn)程。郵槽客戶機(jī)進(jìn)程則負(fù)責(zé)打開郵槽“實(shí)例”,該進(jìn)程是能夠向其中寫入數(shù)據(jù)的唯一一種進(jìn)程。

2.1 郵槽服務(wù)器的詳情

    若想實(shí)現(xiàn)一個(gè)郵槽, 要求開發(fā)一個(gè)服務(wù)器應(yīng)用,來負(fù)責(zé)郵槽的創(chuàng)建。下述步驟解釋了如何編寫一個(gè)基本的服務(wù)器應(yīng)用:

    1)用CreateMailslot  API 函數(shù)創(chuàng)建一個(gè)郵槽句柄.

    2)調(diào)用ReadFile API函數(shù),并使用現(xiàn)成的郵槽句柄,從任何客戶機(jī)接收數(shù)據(jù)。

    3)用CloseHandle這個(gè)API函數(shù),關(guān)閉郵槽句柄。

    可以看出,要開發(fā)一個(gè)郵槽服務(wù)器程序,只需使用極少的API調(diào)用。服務(wù)器進(jìn)程是用CreateMailslot這個(gè)API調(diào)用來創(chuàng)建郵槽的。定義如下:

        HANDLE CreateMailslot(
                  LPCTSTR  lpName,
                  DWORD    nMaxMessageSize,
                  DWORD    lReadTimeout,
                  LPSECURITY_ATTRIBUTES  lpSecurityAttributes
           );

          其中, 第一個(gè)參數(shù)lpName指定郵槽的名字,名字的格式如下:
           \\.\Mailslot\[path]name


          要注意的是,服務(wù)器的名字用一個(gè)小數(shù)點(diǎn)來表示,亦即服務(wù)器就是本地機(jī)器。這樣做是很有必要的,因?yàn)槲覀儾荒茉谶h(yuǎn)程計(jì)算機(jī)上創(chuàng)建郵槽。在lpName參數(shù)中,名字必須以一種獨(dú)一無二的形式表達(dá)??蓪⑺O(shè)為一個(gè)獨(dú)立的名字,也可以在它前面加上一個(gè)完整的目錄路徑。

    nMaxMessageSize參數(shù)定義的是可寫入郵槽的一條消息的最大長度(以字節(jié)為單位)。假如客戶機(jī)寫入的字節(jié)數(shù)多于nMaxMessageSize的設(shè)置,服務(wù)器便不會(huì)接收這條消息。若將它的值設(shè)為0,服務(wù)器便會(huì)接收任意長度的消息。

   在一個(gè)郵槽上,讀操作可以等待或不等待這兩種模式進(jìn)行,具體由lReadTimeout參數(shù)決定。它以毫秒為單位,指定了讀操作需要等候進(jìn)入消息的時(shí)間。若將它的值設(shè)為MAILSLOT_WAIT_FOREVER,那么在進(jìn)入的數(shù)據(jù)可以讀取之前,讀操作便會(huì)無限期地等待下去。若設(shè)為0,讀操作就會(huì)立即返回。

    lpSecurityAttributes參數(shù)決定了為郵槽施加的訪問控制權(quán)限。在Windows NT和Windows2000中,這個(gè)參數(shù)只實(shí)現(xiàn)了一部分,所以同時(shí)還應(yīng)指定一個(gè)null(空)參數(shù)。在郵槽上,唯一能夠施加的安全措施是針對(duì)本地I/O進(jìn)行的----客戶機(jī)試圖將服務(wù)器的名字設(shè)為小數(shù)點(diǎn)(.),以打開一個(gè)郵槽。要想繞過這種安全機(jī)制,客戶機(jī)可指定服務(wù)器的實(shí)際名字,而不是一個(gè)小數(shù)點(diǎn),亦即相當(dāng)于發(fā)出一個(gè)遠(yuǎn)程I/O調(diào)用。在Windows NT和Windows2000中,并未針對(duì)遠(yuǎn)程I/O而實(shí)現(xiàn)lpSecurityAttributes參數(shù),因?yàn)榧偃缑看伟l(fā)出一條消息時(shí),都在客戶機(jī)與服務(wù)器之間建立一個(gè)授權(quán)會(huì)話,那么效率會(huì)顯得十分低下。因此,郵槽僅一部分符合標(biāo)準(zhǔn)文件系統(tǒng)采用的Windows NT和Windows2000安全模型。結(jié)果便是,網(wǎng)絡(luò)中的任何郵槽客戶機(jī)都可將數(shù)據(jù)發(fā)給服務(wù)器。

    用一個(gè)有效的句柄創(chuàng)建了郵槽之后,便可開始數(shù)據(jù)的實(shí)際讀取。服務(wù)器是唯一能從郵槽讀入數(shù)據(jù)的進(jìn)程。服務(wù)器應(yīng)使用ReadFile這個(gè)Win32函數(shù),來進(jìn)行數(shù)據(jù)讀取。對(duì)ReadFile的定義如下:

         BOOL ReadFile(
                  HANDLE       hFile,
                  LPVOID         lpBuffer,
                  DWORD        nNumberOfBytesToRead,
                  LPDWORD    lpNumberOfBytesRead,
                  LPOVERLAPPED  lpOverlapped
          );

        CreateMailslot會(huì)返回一個(gè)句柄hFile.lpBuffer和nNumberOfBytesToRead參數(shù)決定了可從郵槽讀入多少數(shù)據(jù)。特別值得注意的是,這個(gè)緩沖區(qū)的大小應(yīng)該比來自CreateMailslot API調(diào)用的nMaxMessageSize參數(shù)的設(shè)置大。此外,緩沖區(qū)應(yīng)該大于郵槽上的進(jìn)入消息;如果不夠大,ReadFile調(diào)用便會(huì)失敗,并返回一個(gè)ERROR_INSUFFICIENT_BUFFER錯(cuò)誤。lpNumberOfBytesRead參數(shù)用于在ReadFile操作完成后,報(bào)告讀入的實(shí)際字節(jié)數(shù)量。

    利用lpOverlapped參數(shù),我們可以通過異步方式,進(jìn)行數(shù)據(jù)的讀取。該參數(shù)采用的是Win32重疊I/O機(jī)制,在默認(rèn)情況下,ReadFile操作會(huì)處于暫停狀態(tài),直到有數(shù)據(jù)可以讀入為止。重疊I/O只能在Windows NT和windows20000上完成;如果使用的操作系統(tǒng)是Windows 95或Windows 98,那么應(yīng)將該參數(shù)設(shè)為NULL。在程序清單中我們進(jìn)一步闡釋。


    // Serverl.cpp
    #include <windows.h>
    #include <stdio.h>

    void main(void)
    {
         HANDLE   Mailslot;
         char            buffer[256];
         DWORD    NumberOfBytesRead;

          // Create the mailslot
          if ((Mailslot = CreateMailslot(\\\\.\\Mailslot\\Myslot,  0,
                MAILSLOT_WAIT_FOREVER, NULL)) == INVALID_HANDLE_VALUE)
          {
                      printf("Failed to create a mailslot %d\n", GetLastError());
                      return;
           }

           // Read data from the mailslot  forever!
           while (ReadFile(Mailslot, buffer, 256, &NumberOfBytesRead, NULL) != 0)
           {
                         printf("%.*s\n",   NumberOfBytesRead, buffer);
           }
      }


2.2 郵槽客戶機(jī)的詳情

    要想實(shí)現(xiàn)一個(gè)客戶機(jī),需要開發(fā)一個(gè)應(yīng)用程序,對(duì)一個(gè)現(xiàn)有的郵槽進(jìn)行引用和寫入.下述步驟解釋了如何編寫一個(gè)基本的客戶機(jī)應(yīng)用:

    1)使用CreateFile這個(gè)API函數(shù),針對(duì)想向其傳送數(shù)據(jù)的郵槽,打開指向它的一個(gè)引用句柄.

    2)調(diào)用WriteFile這個(gè)API函數(shù), 向郵槽寫入數(shù)據(jù).

    3) 完成了數(shù)據(jù)的寫入后,用CloseHandle這個(gè)API函數(shù),關(guān)閉打開的郵槽句柄.

      如前所述, 采用一種"無連接"的形式,郵槽客戶機(jī)同郵槽服務(wù)器通信.客戶機(jī)打開指向郵槽的一個(gè)引用句柄時(shí),實(shí)際并不建立同郵槽服務(wù)器的一個(gè)連接.要想對(duì)一個(gè)郵槽進(jìn)行引用需要使用CreateFile這個(gè)API調(diào)用.對(duì)它的定義如下:

              HANDLE CreateFile(
                    LPCTSTR         lpFileName,
                    DWORD            dwDesiredAccess,
                    DWORD            dwShareMode,
                    LPSECURITY_ATTRIBUTES   lpSecurityAttributes,
                    DWORD            dwCreatingDisposition,
                    DWORD            dwFlagsAndAttributes,
                    HANDLE           hTemplateFile
                );

   lpFileName參數(shù)用于描述一個(gè)或多個(gè)郵槽,我們可用本章早些時(shí)候介紹的郵槽命名格式,向其寫入數(shù)據(jù).dwDesiredAccess參數(shù)必須設(shè)為GENERIC_WRITE, 因?yàn)榭蛻魴C(jī)只能向服務(wù)器寫入數(shù)據(jù).dwShareMode參數(shù)必須設(shè)為FILE_SHARE_READ,允許服務(wù)器在郵槽上打開和進(jìn)行讀操作.lpSecurityAttributes參數(shù)對(duì)于郵槽不會(huì)有什么效果,應(yīng)將其設(shè)為NULL.dwCreatiionDisposition標(biāo)志應(yīng)設(shè)為OPEN_EXISTING。若一臺(tái)機(jī)器既是客戶機(jī),也是服務(wù)器,這一設(shè)置便顯得尤其重要----如果服務(wù)器沒有創(chuàng)建郵槽,對(duì)API函數(shù)CreateFile的調(diào)用便會(huì)失敗.如果服務(wù)器在遠(yuǎn)程工作,那么.dwCreationDisposition參數(shù)便沒什么意義dwFlagsAndAttributes參數(shù)應(yīng)定義成FILE_ATTRIBUTE_NORMAL. hTemplateFile參數(shù)應(yīng)設(shè)為NULL.

    成功創(chuàng)建一個(gè)句柄后,便可開始向郵槽寫入數(shù)據(jù).請(qǐng)記住,作為客戶機(jī),只能將數(shù)據(jù)寫入郵槽.這可以用Win32函數(shù)WriteFile來做到,定義如下:

        BOOL WriteFile(
                      HANDLE   hFile,
                      LPCVOID  lpBuffer,
                      DWORD    nNumberOfBytesToWrite,
                      LPDWORD lpNumberOfBytesWritten,
                      LPOVERLAPPED lpOverlapped
          );

   其中,hFile參數(shù)是由CreateFile返回的一個(gè)引用句柄。lpBuffer和nNumberOfBytesToWrite參數(shù)決定了有多少字節(jié)從客戶機(jī)發(fā)向服務(wù)器。一條消息的最大長度為64KB。如果當(dāng)初是用一個(gè)域或星號(hào)(*)格式來創(chuàng)建郵槽句柄,那么在Windows NT和Windows2000中,消息的長度限制在424字節(jié)之內(nèi); 而在Windows 95和Windows98中,限制在64KB之內(nèi)。如客戶機(jī)試圖發(fā)送的消息超出了這一長度限制,WriteFile函數(shù)便會(huì)失敗,而且GetLastError函數(shù)會(huì)返回ERROR_BAD_NETPATH錯(cuò)誤。之所以會(huì)出現(xiàn)這一情況,是由于需要以廣播數(shù)據(jù)報(bào)的形式,把消息發(fā)送給網(wǎng)絡(luò)中的所有服務(wù)器。lpNumberOfBytesWritten參數(shù)返回的是當(dāng)WriteFile操作完成后,傳給服務(wù)器的實(shí)際字節(jié)數(shù)量。

    通過lpOverlapped參數(shù),我們可采用異步形式,將數(shù)據(jù)寫入一個(gè)郵槽。由于郵槽最大的特點(diǎn)便是“無連接”的數(shù)據(jù)傳輸,所以WriteFile函數(shù)不會(huì)在I/O調(diào)用的時(shí)候暫停等候。在客戶機(jī)上,這個(gè)參數(shù)應(yīng)設(shè)為NULL。在程序中我們進(jìn)一步闡述。

   


          // Client.cpp
          
          #include <windows.h>
          #include <stdio.h>
              
          void main(int argc,    char  *argv[])
          {
                    HANDLE   Mailslot;
                    DWORD   BytesWritten;
                    CHAR        ServerName[256];
       
                     // Accept a command line argument for the server to send
                    //   a  message to 
                    if  (argc < 2)
                    {
                              printf("Usage: client <server name>\n");
                              return;
                    }
                    
                    sprintf(ServerName,   \\\\%s\\Mailslot\\Myslot,  argv[1]);
                     
                     if ((Mailslot = CreateFile(ServerName,   GENERIC_WRITE,
                           FILE_SHARE_READ,    NULL,   OPEN_EXISTING,    FILE_ATTRIBUTE_NORMAL,
                           NULL))  == INVALID_HANDLE_VALUE)
                     {
                                   printf("CreateFile failed with error %d\n",  GetLastError());
                                   return;
                     }
                   
                     if (WriteFile(Mailslot,  "This is a test", 14,  &BytesWritten, NULL)  == 0)
                     {
                                    printf("WriteFile failed with error %d\n",  GetLastError());
                                     return;
                     }
                     printf("Wrote %d bytes \n", BytesWritten);
                     CloseHandle(Mailslot);
             }


3. 其他郵槽API

   對(duì)郵槽服務(wù)器應(yīng)用來說,它可使用另外兩個(gè)API函數(shù)同郵槽打交道:GetMailslotInfo和SetMailslotInfo.其中,一旦郵槽上有消息可以傳遞,GetMailslotInfo函數(shù)便可負(fù)責(zé)獲取消息的長度信息.利用這個(gè)函數(shù),程序可針對(duì)長度不定的進(jìn)入消息,動(dòng)態(tài)地調(diào)節(jié)其緩沖區(qū).GetMailslotInfo函數(shù)亦可用來對(duì)進(jìn)入數(shù)據(jù)進(jìn)行"輪詢".對(duì)GetMailslotInfo函數(shù)的定義如下:

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

         其中, hMailslot參數(shù)指定自CreateMailslot API調(diào)用返回的一個(gè)郵槽. lpMaxMessageSize參數(shù)設(shè)置可將多大的一條消息寫入郵槽(以字節(jié)為單位).    lpNextSize參數(shù)則以字節(jié)為單位,指出下一條消息的長度.GetMailslotInfo可能會(huì)返回一個(gè)MAILSLOT_NO_MESSAGE值,指出在郵槽之上,目前沒有等待接收的消息。利用這個(gè)參數(shù),服務(wù)器便可在郵槽上輪詢(不斷地查詢)是否有進(jìn)入的消息,防止應(yīng)用程序在ReadFile函數(shù)調(diào)用過程中“凍結(jié)”,傻乎乎地一直等候下去.然而,用這種方式對(duì)數(shù)據(jù)進(jìn)行輪詢并不是一種很好的習(xí)慣.因?yàn)閼?yīng)用程序會(huì)連續(xù)不停地消耗寶貴的CPU資源,以檢查進(jìn)入的數(shù)據(jù)----即使根本沒有需要處理的消息.這樣一來,便會(huì)降低系統(tǒng)的總體性能.如果想防止ReadFile"凍結(jié)"或暫停執(zhí)行,建立你使用Win32的重疊I/O.lpMessageCount參數(shù)指定一個(gè)緩沖區(qū),用于接收等候讀入的消息的總量.lpReadTimeout參數(shù)則指定了另一個(gè)緩沖區(qū),它以毫秒為單位,返回了一次讀操作最多能等候多久的時(shí)間,讓一條消息寫入郵槽.

    SetMailslotInfo函數(shù)用于設(shè)置一個(gè)郵槽的超時(shí)值.超過這個(gè)時(shí)間,讀操作便不再等候進(jìn)入消息.因此,應(yīng)用程序完全有能力將讀操作從"凍結(jié)"狀態(tài)轉(zhuǎn)變成"非凍結(jié)"狀態(tài);或者相反.對(duì)SetMailslotInfo的定義如下:

          BOOL   SetMailslotInfo(
                         HANDLE         hMailslot,
                         DWORD         lReadTimeout
            );

     bMailslot參數(shù)指定一個(gè)自CreateMailslot API調(diào)用返回的郵槽.  lReadTimeout參數(shù)以毫秒為單位,指定一次讀操作等候一條消息寫入郵槽的最長時(shí)間.若將其設(shè)為0,在不存在消息的前提下,讀操作便會(huì)立即返回; 若設(shè)為MAILSLOT_WAIT_FOREVER, 讀操作便會(huì)永遠(yuǎn)等待下去。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
深度探索I/O完成端口
MySQL數(shù)據(jù)庫介紹
VC中的管道技術(shù)
網(wǎng)絡(luò)通訊編程基礎(chǔ)——TCP/UDP/IP Multicast
在VBA中使用WINDOWS API
WinHTTP APIs(1)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服