Basic ClientServer

Basic Client/Server

As we mentioned earlier, mailslots feature a simple client/server design architecture in which data can flow only from a client to a server. The data communication model is one-way, or unidirectional. The server is responsible for creating a mailslot and is the only process that can read data from it. Mailslot clients are processes that open instances of mailslots and are the only processes that can write data to them.

Mailslot Server Details

Implementing a mailslot requires developing a server application to create a mailslot. The following steps describe how to write a basic server application:

  1. Create a mailslot handle using the CreateMailslot API function.

  2. Receive data from any client by calling the ReadFile API function using the mailslot handle.

  3. Close the mailslot handle using the CloseHandle API function.

As you can see, very few API calls are needed to develop a mailslot server application.

Server processes create mailslots using the CreateMailslot API call, which is defined as follows:

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

The first parameter, lpName, specifies the name of the mailslot. The name must have the following form:

\\.\Mailslot\[path]name

Notice that the server name is represented as a dot, which represents the local machine. This is required because you cannot create a mailslot on a remote computer. In the lpName parameter, name must represent a unique name. This might simply be a name, or a full directory path might precede it.

The nMaxMessageSize parameter defines the maximum size—in bytes—of a message that can be written to a mailslot. If a client writes more than nMaxMessageSize bytes, the server doesn't see the message. Specifying the value 0 allows the server to accept a message of any size.

Read operations can operate in blocking or nonblocking mode on a mailslot, depending on the lReadTimeout parameter, which determines the amount of time in milliseconds that read operations wait for incoming messages. Specifying the value MAILSLOT_WAIT_FOREVER allows read operations to block and wait indefinitely until incoming data is available to be read. If you specify 0, read operations return immediately. We discuss details of reading later in this chapter. The lpSecurityAttributes parameter determines access control rights to a mailslot. Using Windows 95, Windows 98, or Windows Me, this parameter must be NULL because you cannot apply security to objects. Using the Windows NT platform, this parameter is only partially implemented, so you should also specify a NULL parameter. The only security that you can enforce on a mailslot is for local I/O, in which a client attempts to open a mailslot with a dot (.) for the server name. A client can get around this security by specifying the server's actual name instead of a dot (.), as when making a remote I/O call. The lpSecurityAttributes parameter is not implemented for remote I/O on the Windows NT platform because of the extreme inefficiency of forming an authenticated session between the client and the server every time a message is sent. Mailslots, therefore, only partially follow the Windows NT security model found in the standard file systems. As a consequence, any mailslot client on your network can send data to your server.

After a mailslot is created with a valid handle, you can begin reading data. The server is the only process that can read data from a mailslot. The server should use the Win32 ReadFile function to accomplish this. ReadFile is defined as follows:

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

CreateMailslot returns the handle hFile. The lpBuffer and nNumberOfBytesToRead parameters determine how much data can be read off a mailslot. It is important to make the size of this buffer greater than the nMaxMessageSize parameter from the CreateMailslot API call. Additionally, the buffer must be larger than incoming messages on the mailslot; if it is not larger, ReadFile will fail with the error ERROR_INSUFFICIENT_BUFFER. The lpNumberOfBytesRead parameter reports the actual number of bytes read when the ReadFile operation completes.

The lpOverlapped parameter provides a way to read data asynchronously off a mailslot. This parameter uses the Win32 overlapped I/O mechanism, which we describe in greater detail in Chapter 20. By default, the ReadFile operation blocks (waits) on I/O until data is available for reading. Overlapped I/O can be accomplished only on the Windows NT platform; you should specify NULL for this parameter when using Windows 95, Windows 98, or Windows Me. The following code further demonstrates how to write a simple mailslot server application.

// Server1.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);     } }

Mailslot Client Details

Implementing a client requires developing an application to reference and write to an existing mailslot. The following steps describe how to write a basic client application:

  1. Open a reference handle to the mailslot we want to send data to using the CreateFile API.

  2. Write data to the mailslot by calling the WriteFile API.

  3. Once you are finished writing data, close the mailslot handle using the CloseHandle API.

As we described earlier, mailslot clients communicate to mailslot servers in a connectionless manner. When a client opens a reference handle to a mailslot, the client does not form a connection to the mailslot server. Mailslots are referenced using the CreateFile API call, which is defined as follows:

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

The lpFileName parameter describes one or more mailslots that can be written to using the mailslot name format described earlier. Table 19-2 describes mailslot naming conventions in greater detail. The dwDesiredAccess parameter must be set to GENERIC_WRITE because a client can only write data to the server. The dwShareMode parameter must be set to FILE_SHARE_READ, allowing the server to open and perform read operations on the mailslot. The lpSecurityAttributes parameter has no effect on mailslots and should be set to NULL. The dwCreationDisposition flag should be set to OPEN_EXISTING. This setting is useful when a client and a server are operating on the same machine: If the server has not created the mailslot, the CreateFile API function fails. The dwCreationDisposition parameter has no effect if the server is operating remotely. The dwFlagsAndAttributes parameter should be defined as FILE_ATTRIBUTE_NORMAL. The hTemplateFile parameter should be set to NULL.

Table 19-2 Mailslot Name Types

Name Format

Description

\\.\mailslot\name

Identifies a local mailslot on the same machine

\\servername\mailslot\name

Identifies a remote mailslot server named servername

\\domainname\mailslot\name

Identifies all mailslots of a particular name in the specified domain

\\*\mailslot\name

Identifies all mailslots of a particular name in the system's primary domain

After a handle has been successfully created, you can begin writing data to a mailslot. Remember, a client can only write data to the mailslot. This can be accomplished using the Win32 WriteFile function, defined as follows:

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

The hFile parameter is the reference handle that CreateFile returns. The lpBuffer and nNumberOfBytesToWrite parameters determine how many bytes will be sent from the client to the server. The maximum size of a message is 64 KB. If the mailslot handle was created using a domain or asterisk format, the message size is limited to 424 bytes on Windows NT and 64 KB on Windows 95, Windows 98, and Windows Me. If a client attempts to send a message that exceeds those limits, the WriteFile function fails and the GetLastError function returns ERROR_BAD_NETPATH. This happens because the message is sent as a broadcast datagram to all servers on the network. The lpNumberOfBytesWritten parameter returns the number of bytes sent to a server when the WriteFile operation completes.

The lpOverlapped parameter provides a way to write data asynchronously to a mailslot. Because mailslots feature connectionless data transfer, the WriteFile function is not subject to blocking on I/O calls. This parameter should be set to NULL on the client. The following code further demonstrates how to write a simple mailslot client application.

// 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); }



Network Programming for Microsoft Windows
Network Programming for Microsoft Windows (Microsoft Professional Series)
ISBN: 0735605602
EAN: 2147483647
Year: 2001
Pages: 172
Authors: Anthony Jones

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net