邮槽(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);
}

转载于:https://www.cnblogs.com/BIGFOOT/archive/2008/10/28/1321157.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值