mailslot又一例

Platform and Performance Considerations

 

Mailslots on Windows 95, Windows 98, and Windows Me platforms have three limitations that you should be aware of: 8.3-character name limits, inability to cancel blocking I/O requests, and timeout memory leaks.

 

8.3-Character Name Limits

 

Windows 95, Windows 98, and Windows Me platforms silently limit mailslot names to an 8.3-character name format. This causes interoperability problems between Windows 95, Windows 98, Windows Me, and Windows NT. For example, if you create or open a mailslot with the name //./Mailslot/Mymailslot, Windows 95, Windows 98, and Windows Me will actually create and reference the mailslot as //./Mailslot/Mymailsl. The CreateMailslot() and CreateFile() functions succeed even though name truncation occurs. If a message is sent from Windows NT to Windows 95, Windows 98, or Windows Me, or vice versa, the message will not be received because the mailslot names do not match. If both the client and the server are running on Windows 95, Windows 98, or Windows Me machines, there isn't a problem, the name is truncated on both the client and the server. An easy way to prevent interoperability problems is to limit mailslot names to eight characters or less.

 

Inability to Cancel Blocking I/O Requests

 

Windows 95, Windows 98, and Windows Me platforms also have a problem with canceling blocking I/O requests. Mailslot servers use the ReadFile() function to receive data. If a mailslot is created with the MAILSLOT_WAIT_FOREVER flag, read requests block indefinitely until data is available. If a server application is terminated when there is an outstanding ReadFile() request, the application hangs forever. The only way to cancel the application is to reboot Windows. A possible solution is to have the server open a handle to its own mailslot in a separate thread and send data to break the blocking read request. The following code demonstrates this solution in detail:

 

// Server sample

#include<windows.h>

#include<stdio.h>

#include<conio.h>

 

BOOL StopProcessing;

 

DWORD WINAPI ServeMailslot(LPVOID lpParameter);

voidSendMessageToMailslot(void);

 

voidmain(void)

{

    DWORD ThreadId;

    HANDLE MailslotThread;

 

    StopProcessing = FALSE;

    MailslotThread = CreateThread(NULL, 0, ServeMailslot, NULL, 0, &ThreadId);

 

    printf("Press a key to stop the server/n");

    _getch();

 

    // Mark the StopProcessing flag to TRUE so that when ReadFile breaks, our server thread will end

    StopProcessing = TRUE;

    // Send a message to our mailslot to break the ReadFile call in our server

     SendMessageToMailslot();

    // Wait for our server thread to complete

    if (WaitForSingleObject(MailslotThread, INFINITE) == WAIT_FAILED)

    {

        printf("WaitForSingleObject failed with error %d/n", GetLastError());

        return;

    }

}

 

// Function: ServeMailslot

// Description: This function is the mailslot server worker function to process all incoming mailslot I/O

DWORD WINAPI ServeMailslot(LPVOID lpParameter)

{

    char buffer[2048];

    DWORD NumberOfBytesRead;

    DWORD Ret;

    HANDLE Mailslot;

 

    if ((Mailslot = CreateMailslot(".//mailslot//myslot", 2048, MAILSLOT_WAIT_FOREVER, NULL)) == INVALID_HANDLE_VALUE)

    {

        printf("Failed to create a MailSlot %d/n", GetLastError());

        return 0;

    }

 

    while((Ret = ReadFile(Mailslot, buffer, 2048, &NumberOfBytesRead, NULL)) != 0)

    {

        if (StopProcessing)

            break;

        printf("Received %d bytes/n", NumberOfBytesRead);

    }

    CloseHandle(Mailslot);

    return 0;

}

 

// Function: SendMessageToMailslot

// Description:

//     The SendMessageToMailslot function is designed to send a

//     simple message to our server so we can break the blocking ReadFile API call

voidSendMessageToMailslot(void)

{

    HANDLE Mailslot;

    DWORD BytesWritten;

 

    if ((Mailslot = CreateFile(".//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;

    }

 

    if (WriteFile(Mailslot, "STOP", 4, &BytesWritten, NULL) == 0)

    {

        printf("WriteFile failed with error %d/n", GetLastError());

        return;

    }

    CloseHandle(Mailslot);

}

 

Timeout Memory Leaks

 

The final problem with Windows 95, Windows 98, and Windows Me platforms worth mentioning is memory leaks, which can occur when you're using timeout values on mailslots. When you create a mailslot using the CreateMailslot() function with a timeout value greater than 0, the ReadFile() function leaks memory when the timeout expires and the function returns FALSE. After many calls to the ReadFile() function, the system becomes unstable and subsequent ReadFile() calls with timers that expire start returning TRUE. As a result, the system is no longer able to execute other MS-DOS applications. To work around this, create the mailslot with a timeout value of either 0 or MAILSLOT_WAIT_FOREVER. This prevents an application from using the timeout mechanism, which causes the actual memory leak.

 

Program Examples

 

Client Program Example

 

Create a new empty Win32 console mode application and add the project/solution name.

 

 

Add the following source code.

 

// Creating and writing mailslot example

#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 error code %d./n", GetLastError());

      return FALSE;

   }

   else

   {

               printf("WriteFile() is OK!/n");

               printf("Slot written to successfully./n");

   }

 

   return TRUE;

}

 

intmain(int argc, char **argv)

{

   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)

   {

               // GetLastError() code - http://msdn.microsoft.com/en-us/library/ms679360(VS.85).aspx

               printf("CreateFile() failed with error code %d./n", GetLastError());

               return FALSE;

   }

   else

               printf("CreateFile() is OK!/n");

 

   WriteSlot(hFile, TEXT("Message one for mailslot."));

   WriteSlot(hFile, TEXT("Message two for mailslot."));

   Sleep(5000);

   WriteSlot(hFile, TEXT("Message three for mailslot."));

 

   if(CloseHandle(hFile) != 0)

               printf("hFile handle was closed successfully!/n");

   else

               printf("Fail to close hFile handle, error %d/n", GetLastError());

 

   return TRUE;

}

 

Build and run the project.

 

   

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

 

We will test this client with the following server program example.

 

Server Program Example

 

Create a new empty Win32 console mode application and add the project/solution name.

 

 

Add the following source code.

 

// Server example: Create and read mailslots

#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, // 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 with error code %d./n", GetLastError());

        return FALSE;

    }

    else

        printf("GetMailslotInfo() is fine!/n");

 

    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(lpszBuffer == NULL)

            return FALSE;

        lpszBuffer[0] = '/0';

 

        fResult = ReadFile(hSlot, lpszBuffer, cbMessage, &cbRead, &ov);

 

        if (!fResult)

        {

            printf("ReadFile() failed with error code %d./n", GetLastError());

            GlobalFree((HGLOBAL) lpszBuffer);

            return FALSE;

        }

        else

           printf("ReadFile() is OK!/n");

 

        // 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 with error code %d/n", GetLastError());

            return FALSE;

        }

        else

           printf("GetMailslotInfo() is OK!/n");

    }

 

    if(CloseHandle(hEvent) != 0)

               printf("hEvent handle was closed successfully!/n");

   else

               printf("Fail to close hEvent handle, error %d/n", GetLastError());

 

    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 error code %d/n", GetLastError());

        return FALSE;

    }

    printf("CreateMailslot() is OK!/n");

    return TRUE;

}

 

voidmain(int argc, char** argv)

{

   MakeSlot(SlotName);

 

   while(TRUE)

   {

      ReadSlot();

      Sleep(2000);

   }

}

 

Build and run the project.

 

 

Testing Client-Server Program Examples

 

Let test both the client and the server program example. Firstly run the server program.

 

 

Then, run the client program.

 

 

The previous server program sample output is shown below.

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值