Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VisualC++

MailShot: From Client to Server (With Love)

5.00/5 (3 votes)
7 Jan 2012CPOL2 min read 30.7K  
Simple tip and trick for Mail Slot
MailSlot is one way IPC mechanism is present in window, where server takes a passive role in receiving message from the client. This means that the client can only write and server can only read, vice versa is not possible, rather I never tried it.

According to MSDN
A mailslot is a mechanism for one-way interprocess communications (IPC). Applications can store messages in a mailslot. The owner of the mailslot can retrieve messages that are stored there. These messages are typically sent over a network to either a specified computer or to all computers in a specified domain. A domain is a group of workstations and servers that share a group name.”

Only disadvantage I feel about this mechanism is that the limit of maximum message size is 424 bytes and instead of using reliable TCP service, it relies more on datagram packets. So keep both points in your mind while designing or using MailSlot in your application.

Through Wikipedia article[^] about MailSlot, I came to know NET SEND service, is created on MailSlots only, however I couldn’t find any official or unofficial link from Microsoft on the same.

So writing application based on MailSlot, you have to utilize service of these APIS (Description is copied word by word from MSDN):

  1. CreateMailSlot[^]: Creates a mailslot with the specified name.
  2. GetMailslotInfo[^]: Retrieves information about the specified mailslot.
  3. SetMailslotInfo[^]: Sets the time-out value used by the specified mailslot for a read operation.
  4. ReadFile: Above three and this function is used by server mailslot to create and read message in its mailslot queue.
  5. CreateFile: This function is utilized by the client to open existing MailSlot.
  6. WriteFile: This function is utilized by the client to write message for server mailslot, if CreateFile call is successful.

Now to create Server Mail Slot:

C++
       m_hServerMailSlot =
	::CreateMailslot(m_szSlotName, // Name of the Mail Slot
					 0, // no limit for the message Size
					 0,
					 NULL // Security Attribute
					 );

	// check is we are success full opening the mail slot

	if(m_hServerMailSlot == INVALID_HANDLE_VALUE)
	{
		LPVOID lpMsgBuf;
		
		FormatMessage( 
			FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM | 
			FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			GetLastError(),
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
			(LPTSTR) &lpMsgBuf,
			0,
			NULL 
			);
		
		::MessageBox( NULL, (LPCTSTR)lpMsgBuf, L"Error", MB_OK | MB_ICONINFORMATION );
		
		LocalFree( lpMsgBuf );		
		return;
	}

	/// If everything Ok , Just return! and Display message that we are successful in creating the Socket
	
MessageBox(L"Creation of Server MailSlot is successfull!!");


To Create Client MailSlot, which opens Server MailSlot

C++
m_hClientMailSlot =
        CreateFile(m_szSlotName,
        GENERIC_WRITE,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        (HANDLE) NULL);

    if(m_hClientMailSlot == INVALID_HANDLE_VALUE)
    {
        MessageBox(L"unable to create client mail Slot");
        return;
    }


The communication between server and the client. The pseudo algorithm would be:
From Client Side:

  • Open existing server mailslot using CreateFile API.
  • If successful, write to mailslot, using WriteFile API.

Code (includes client creation again)
C++
//make  temporary slot handle , write information and leave

	m_hClientMailSlot =
		CreateFile(m_szSlotName,
		GENERIC_WRITE,
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		(HANDLE) NULL);

	if(m_hClientMailSlot == INVALID_HANDLE_VALUE) 
	{
		MessageBox(L"unable to create client mail Slot");
		return;
	}

	TCHAR szData[MAX_PATH];
	m_ctlEditWrite.GetWindowTextW(szData,MAX_PATH);
	DWORD bytesWritten =0;

	BOOL bFlag = WriteFile(m_hClientMailSlot,
							szData,
							_tcslen(szData) *sizeof(TCHAR),
							&bytesWritten,
							NULL);	
	CloseHandle(m_hClientMailSlot);


From Server Side

  • Call GetMailslotInfo to retrieve number of message and message length.
  • If messageCount is more than 0 (zero), call ReadFile API to read message from MailSlot Queue.


Code

C++
    DWORD lpdNextMsgSize=0,lpdMessageCount=0,bytesRead=0;

BOOL bFlag = GetMailslotInfo(m_hServerMailSlot,
                (LPDWORD)NULL,//Maximum Message Size
                &lpdNextMsgSize,
                &lpdMessageCount,
                (LPDWORD) NULL);

if(bFlag == false) return;

if(lpdNextMsgSize == MAILSLOT_NO_MESSAGE) return;

TCHAR *szBuffer = new TCHAR[lpdNextMsgSize +1];
memset(szBuffer,0,(lpdNextMsgSize +1) * sizeof(TCHAR));

ReadFile(m_hServerMailSlot,szBuffer,lpdNextMsgSize,&bytesRead,NULL);

szBuffer[bytesRead]= '\0';

MessageBox(szBuffer);

delete [] szBuffer;

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)