zoukankan      html  css  js  c++  java
  • 邮槽(Mailslot)

     

    Microsoft Windows NTWindows 2000Windows 95Windows 98(含第二版)-但不包括Windows CE-提供了一种简单"通信"interprocess communication,I P C)机制。个机制的名字非常古怪,叫作""M a i l s l o t)。用最简单,通过邮槽,客程可将消息送或广播一个或多个服程。在同一台算机的不同程之,或在跨越整个网的不同算机的程之行消息的传输

     

    传输安全性:

    由于槽是围绕一个广播通信体系设计出来的,所以当然不能指望能通实现数据的"可靠"传输

     

    缺点:

    槽最大的一个缺点便是只允从客机到服器,建立一不可靠的向数据通信。

    而另一方面,槽最大的一个点在于,它使客用能非常容易地将广播消息一个或多个服用。

     

    协议

    由于槽要依Windows文件系在网上来建和传输数据,所以接口是"协议"的。

    制自己的用程序,便不必心基络传协议细节,不必知道它在一个网中如何在程之建立通信。

     

    windows重定向器的密切

    槽通一个网算机程通信windows文件系需要依windows重定向器,

    使用"器消息"S M B协议,将数据从客传给器。

    消息通常是通""传输方式来送的,但亦可Windows重定向器在Windows NTWindows 2000上使用"面向"传输方式。至于具体采用哪方式,要由消息的度决定。

     

    接与面向

    槽通常用"数据"Datagram,以一""的方式在网传递消息。

    但在Windows NTWindows 2000中,若消息度超426个字,便必在一个SMB之上,

    "面向"协议进传输,而不再采用无接的"数据"形式。

    这样一来,在消息大的情况下,便可保定、高效传输

    然而,此再也不能将一条消息从客机广播多个服器。

     

    "面向"传输,它必然是一""通信:一个客一个服器!

    在不同的程之,使用"面向"传输方式,往往可保数据传输的可靠性。

     

    要想保Windows平台之完全正常地通信,烈建将消息度限制在424,或者更短。

    如果行面向接的传输,可考使用命名管道,而不是简单 

    --------------

    基本客机/服

    槽建立的简单的客机/服设计体系中,数据只能从客到服器,数据通信是行的。服程的职责建一个槽,而且是能从取数据的唯一一个程。槽客则负责开邮槽的""该进程是能向其中写入数据的唯一一种进器的

    若想实现一个槽,要求开发一个服用,来负责邮槽的建。

    下述步骤了如何写一个基本的服用:

    1) CreateMailslot API函数建一个槽句柄。

    2) ReadFile API函数,并使用成的槽句柄,从任何机接收数据。

    3) CloseHandleAPI函数,关闭邮槽句柄。

     

    可以看出,要开发一个槽服器程序,只需使用极少的API用。

    程是用CreateMailslotAPI用来槽的。定如下:

     

    HANDLE CreateMailslos(

      LPCTSTR lpName,

      DWORD nMaxMessageSize,

      DWORD lReadTimeout,

      LPSECURITY_ATTURIBUTES lpSecurityAttributes

      )

    参数明:

    lpName

    参数lpName指定槽的名字。名字的格式如下:

    \\ .\Mailslot\[path]name

    要注意的是,服器的名字用一个小数点来表示,亦即服器就是本地机器。

    这样做是很有必要的,因不能在算机上槽。

    lpName参数中,名字必以一独一无二的形式表达。

    可将它设为一个独立的名字,也可以在它前面加上一个完整的目路径。

    nMaxMessageSize

    nMaxMessageSize参数定的是可写入槽的一条消息的最大度(以字节为单位)。

    假如客写入的字数多于nMaxMessageSize置,服器便不会接收条消息。

    若将它的值设为0,服器便会接收任意度的消息。

    lReadTimeout

    在一个槽上,操作可以等待或不等待模式行,具体由lReadTimeout参数决定。

    它以毫秒为单位,指定了操作需要等候入消息的时间

    若将它的值设为MAILSLOT_WAIT_FOREVER,那入的数据可以取之前,操作便会无限期地等待下去。

    设为0 操作就会立即返回。

    LpSecurityAttributes

    LpSecurityAttributes参数决定了为邮槽施加的访问控制

     

    用一个有效的句柄建了槽之后,便可始数据的实际读取。服器是唯一能从

    入数据的程。服使用ReadFileWin32函数,来行数据的取。

    ReadFile的定如下:

    BOOL ReadFile(

     HANDLE hFile,

     LPVOID lpBuffer,

     DWORD nNumberOfBytesToRead,

     LPDOWRD lpNumberOfBytesRead,

     LPOVERLAPPED lpOverlapped

     )

    参数明如下:

    CreateMailslot会返回一个句柄hFile

    lpBuffernNumberOfBytesToRead参数决定了可从入多少数据。

    别值得注意的是,冲区的大小应该比来自CreateMailslot API用的nMaxMessageSize参数的置大。

    此外,冲区应该大于槽上的入消息;

    如果不大,ReadFile 用便会失,并返回一个ERROR_INSUFFICIENT_BUFFER 错误

    lpNumberOfBytesRead参数用于在ReadFile操作完成后,入的实际数量。

    利用lpOverlapped参数,我可以通方式,行数据的取。

     

    槽示例

    #include

    #include

     

    int main(void)

    {

     HANDLE Mailslot;

     char Buffer[256];

     DWORD NumberOfBytesRead;

     

     if ((Mailslot = CreateMailslot("\\\\.\\Mailslot\\Myslot",0,MAILSLOT_WAIT_FOREVER,NULL)) == INVALID_HANDLE_VALUE)

     {

      printf("Failed to Create a mailslot %d\n",GetLastError());

      return -1;

     }

     

     while (ReadFile(Mailslot,Buffer,256,&NumberOfBytesRead,NULL) != 0)

     {

      printf("%.*s\n",NumberOfBytesRead,Buffer);

     }

     return 0;

    }

     

    槽客机的

     

     

    要想实现一个客机,需要开发一个用程序,一个有的行引用和写入。

    下述步骤了如何写一个基本的客用:

    1) 使用CreateFileAPI函数,针对想向其送数据的槽,打指向它的一个引用句柄。

    2) WriteFileAPI函数,向槽写入数据。

    3) 完成了数据的写入后,用CloseHandleAPI函数,关闭槽句柄。

     

    如前所述,采用一""的形式,槽客机同槽服器通信。

    机打指向槽的一个引用句柄实际并不建立同槽服器的一个接。

    要想一个行引用,需要使用CreateFileAPI用。它的定如下:

    HANDLE WriteFile(

      LPCSTR lpFileName,

      DWORD dwDesierdAccess,

      DWORD dwShareMode,

      LPSECURITY_ATTURIBUTES lpSecurityAttributes,

      DWORD dwCreationDisposition,

      DWORD dwFlagAndAttributes,

      HANDLE hTempLateFile

      );

     

    参数明:

    lpFileName参数用于描述一个或多个槽,可以采用如下的槽命名格式,向其写入数据。

    \\.\mailslot\name 定同一台机器上的一个本地

    \\servername\mailslot\name 定名servername的一个槽服

    \\domainname\mailslot\name 定在指定的domain(域)内,使用特定name(名字)的所有

    \\*\mailslot\name 定系主域内,定特定name(名字)的所有

     

    dwDesiredAccess参数必须设为GENERIC_WRITE,因机只能向服器写入数据。

    dwShareMode参数必须设为FILE_SHARE_READ,允器在槽上打操作。

    lpSecurityAttributes参数槽不会有什效果,将其设为NULL

    dwCreationDisposition应设为OPEN_EXISTING

    若一台机器既是客机,也是服器,置便得尤其重要-如果服器没有槽,

    API函数CreateFile用便会失。如果服器在程工作,那dwCreationDisposition参数便没什

    dwFlagsAndAttributes参数FILE_ATTRIBUTE_NORMAL

    hTemplateFile参数应设为NULL

     

    成功建一个句柄后,便可始向槽写入数据。请记住,作机,只能将数据写入槽。

    可以用Win32函数WriteFile来做到,定如下:

    BOOL WriteFile(

     HANDLE hFile,

     LPCVOID lpBuffer,

      DWORD nNumberOfBytesToWrite,

     LPDWORD lpNumberOfBytesWrite,

     LPOVERLAPPED lpOverlapped

    );

    参数明:

    其中,hFile参数是由CreateFile返回的一个引用句柄。

    lpBuffernNumberOfBytesToWrite参数决定了有多少字从客向服器。

    一条消息的最大6 4 K B 如果当初是用一个域或星号(*)格式来槽句柄,

    Windows NTWindows 2000中,消息的度限制在4 2 4之内;

    而在Windows 95Windows 98中,限制在6 4 K B之内。

    如客试图发送的消息超出了度限制, WriteFile函数会便失

    而且GetLastError函数会返回ERROR_BAD_NETPATH错误

    之所以会出现这一情况,是由于需要以广播数据的形式,把消息中的所有服器。

    lpNumberOfBytesWritten参数返回的是当WriteFile操作完成后,传给器的实际数量。

    lpOverlapped参数,我可采用异形式,将数据写入一个槽。

    由于槽最大的特点便是""的数据传输,所以WriteFile函数不会在I/O用的停等候。

    在客机上,个参数应设为NULL

     

     

    #include "stdafx.h"

    #include

    #include

    int _tmain()

    {

     HANDLE Mailslot;

     DWORD BytesWritten;

     char ServerName[256];

     

     if (Mailslot == CreateFile("\\\\%s\\Mailslot\\Myslot",GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL) == INVALID_HANDLE_VALUE)

     {

      printf("CreateFile failed with Error:%d\n",GetLastError());

      return -1;

     }

     

     if (WriteFile(Mailslot,"This is b Test!",14,&BytesWritten,NULL) == 0)

     {

      printf("WriteFile with error:%d\n",GetLastError());

      return -1;

     }

    以下内容是MSN关于Mailslot的例子:

     

    #include <windows.h>
    #include <tchar.h>
    #include <stdio.h>
    #include <strsafe.h>

    HANDLE hSlot;
    LPTSTR SlotName = TEXT("\\\\.\\mailslot\\sample_mailslot");

    BOOL ReadSlot()
    {
        DWORD cbMessage, cMessage, cbRead;
        BOOL fResult;
        LPTSTR lpszBuffer;
        TCHAR achID[80];
        DWORD cAllMessages;
        HANDLE hEvent;
        OVERLAPPED ov;
     
        cbMessage = cMessage = cbRead = 0;

        hEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("ExampleSlot"));
        if( NULL == hEvent )
            return FALSE;
        ov.Offset = 0;
        ov.OffsetHigh = 0;
        ov.hEvent = hEvent;
     
        fResult = GetMailslotInfo( hSlot, (LPDWORD) NULL, &nMsgSize, &nMsgs,(LPDWORD) NULL);   // no read time-out
     
        if (!fResult)
        {
            printf("GetMailslotInfo failed with %d.\n", GetLastError());
            return FALSE;
        }
     
        if (cbMessage == MAILSLOT_NO_MESSAGE)
        {
            printf("Waiting for a message...\n");
            return TRUE;
        }
     
        cAllMessages = cMessage;
     
        while (cMessage != 0)  // retrieve all messages
        {
            // Create a message-number string.
     
            StringCchPrintf((LPTSTR) achID,
                80,
                TEXT("\nMessage #%d of %d\n"),
                cAllMessages - cMessage + 1,
                cAllMessages);

            // Allocate memory for the message.
     
            lpszBuffer = (LPTSTR) GlobalAlloc(GPTR,
                lstrlen((LPTSTR) achID)*sizeof(TCHAR) + cbMessage);
            if( NULL == lpszBuffer )
                return FALSE;
            lpszBuffer[0] = '\0';
     
            fResult = ReadFile(hSlot,
                lpszBuffer,
                cbMessage,
                &cbRead,
                &ov);
     
            if (!fResult)
            {
                printf("ReadFile failed with %d.\n", GetLastError());
                GlobalFree((HGLOBAL) lpszBuffer);
                return FALSE;
            }
     
            // Concatenate the message and the message-number string.
     
            StringCbCat(lpszBuffer,
                        lstrlen((LPTSTR) achID)*sizeof(TCHAR)+cbMessage,
                        (LPTSTR) achID);
     
            // Display the message.
     
            _tprintf(TEXT("Contents of the mailslot: %s\n"), lpszBuffer);
     
            GlobalFree((HGLOBAL) lpszBuffer);
     
            fResult = GetMailslotInfo(hSlot,  // mailslot handle
                (LPDWORD) NULL,               // no maximum message size
                &cbMessage,                   // size of next message
                &cMessage,                    // number of messages
                (LPDWORD) NULL);              // no read time-out
     
            if (!fResult)
            {
                printf("GetMailslotInfo failed (%d)\n", GetLastError());
                return FALSE;
            }
        }
        CloseHandle(hEvent);
        return TRUE;
    }

    BOOL WINAPI MakeSlot(LPTSTR lpszSlotName)
    {
        hSlot = CreateMailslot(lpszSlotName,
            0,                             // no maximum message size
            MAILSLOT_WAIT_FOREVER,         // no time-out for operations
            (LPSECURITY_ATTRIBUTES) NULL); // default security
     
        if (hSlot == INVALID_HANDLE_VALUE)
        {
            printf("CreateMailslot failed with %d\n", GetLastError());
            return FALSE;
        }
        return TRUE;
    }

    void main()
    {
       MakeSlot(SlotName);

       while(TRUE)
       {
          ReadSlot();
          Sleep(3000);
       }
    }

    /****************************************************************************************************/
    #include <windows.h>
    #include <stdio.h>

    LPTSTR SlotName = TEXT("\\\\.\\mailslot\\sample_mailslot");

    BOOL WriteSlot(HANDLE hSlot, LPTSTR lpszMessage)
    {
       BOOL fResult;
       DWORD cbWritten;
     
       fResult = WriteFile(hSlot,
         lpszMessage,
         (DWORD) (lstrlen(lpszMessage)+1)*sizeof(TCHAR), 
         &cbWritten,
         (LPOVERLAPPED) NULL);
     
       if (!fResult)
       {
          printf("WriteFile failed with %d.\n", GetLastError());
          return FALSE;
       }
     
       printf("Slot written to successfully.\n");

       return TRUE;
    }

    int main()
    {
       HANDLE hFile;

       hFile = CreateFile(SlotName,
         GENERIC_WRITE,
         FILE_SHARE_READ,
         (LPSECURITY_ATTRIBUTES) NULL,
         OPEN_EXISTING,
         FILE_ATTRIBUTE_NORMAL,
         (HANDLE) NULL);
     
       if (hFile == INVALID_HANDLE_VALUE)
       {
          printf("CreateFile failed with %d.\n", GetLastError());
          return FALSE;
       }
     
       WriteSlot(hFile, TEXT("Message one for mailslot."));
       WriteSlot(hFile, TEXT("Message two for mailslot."));

       Sleep(5000);

       WriteSlot(hFile, TEXT("Message three for mailslot."));
     
       CloseHandle(hFile);
     
       return TRUE;
    }

    /*****************************************************************************/

    #include <windows.h>
    #include <stdio.h>

    HANDLE hSlot;
    LPTSTR Slot = TEXT("\\\\.\\mailslot\\sample_mailslot");

    BOOL WINAPI MakeSlot(LPTSTR lpszSlotName)
    {
        hSlot = CreateMailslot(lpszSlotName,
            0,                             // no maximum message size
            MAILSLOT_WAIT_FOREVER,         // no time-out for operations
            (LPSECURITY_ATTRIBUTES) NULL); // default security
     
        if (hSlot == INVALID_HANDLE_VALUE)
        {
            printf("CreateMailslot failed with %d\n", GetLastError());
            return FALSE;
        }
        else printf("Mailslot created successfully.\n");
        return TRUE;
    }
    void main()
    {
       MakeSlot(Slot);
    }

  • 相关阅读:
    JavaSE知识-14(正则表达式&常用工具类)
    JavaSE知识-13(StringBuffer&数组排序)
    JavaSE知识-12(String类)
    JavaSE知识-11(Eclipse使用以及Object类型)
    JavaSE知识-10(面向对象_权限修饰符&匿名内部类)
    JavaSE知识-09(面向对象_多态&抽象类&接口)
    JavaSE知识-08(面向对象_继承&方法&final)
    JavaSE知识-07(面向对象-构造方法&静态static)
    20145205 20145231 《信息安全系统设计基础》第二次实验
    20145231 《信息安全系统设计基础》第9周学习总结
  • 原文地址:https://www.cnblogs.com/BIGFOOT/p/1321157.html
Copyright © 2011-2022 走看看