Sample: Named Pipe Client/Server Demonstration
Summary:
NPCLIENT and NPSERVER demonstrate the use of named pipes.
The basic design consist of a server application serving
multiple client applications. The user can use the client
applications as an interface to all of the other client
applications via the server. The effect is a simple
communication program that can be used over the network
between multiple clients.
More Information:
The actual implementation works by having the NPSERVER
application launch a new thread, which creates and services
a new instance of the server side of the named pipe every
time a client connects to it. You need only start one
instance of the NPSERVER application. It will service up to
100 instances of the NPCLIENT application. (Note that the
100 instance limit is hard coded into the sample. It does
not reflect the number of named pipe instances you can
create, which is virtually infinite.)
TO USE:
Start an instance of NPSERVER. A window will appear.
Start an instance of NPCLIENT. Two dialog boxes will
appear, one on top of the other. The top level dialog box
will prompt you for a share name and a client or user name.
If the instance of NPCLIENT is local to (on the same machine
as) the NPSERVER instance, enter a '.' for the share name.
Otherwise, enter the machine name of the server that the
NPSERVER instance was started on, i.e. 'FoobarServer'. For
the client or user name, enter any name you wish to be
identified with. Hit enter or click the OK button.
The upper dialog box will go away, and you'll see the Client
dialog box of NPCLIENT. It consists of two edit fields and
a 'Send' button. You will be able to read messages from
other clients (and yourself) in the larger/upper edit field.
(Note, if the message seems garbled, make sure the cursor of
the edit field is located in the lower left hand corner of
the field.) The smaller edit field is used to type
messages. To send a message: type something in the
lower/smaller edit field, and hit enter or click the Send
button. The message will appear in the larger edit field of
all the clients connected to the NPSERVER instance;
prepended by the user name you selected. Note that the user
name you selected will be entered into the caption bar of
the NPCLIENT instance. This allows you to more easily keep
track of multiple instances of NPCLIENT on the same machine.
At the same time the top level dialog box was dismissed from
the NPCLIENT instance, the NPSERVER window was updated with
the picture of a red spool of thread accompanied by the user
name you selected. This red spool indicates an active
client thread connected to NPSERVER. The spool may be
connected to other spools with a thin blue line (similar to
the way the File Manager connects files or directories).
Any time a client disconnects from NPSERVER; the spool
representing it will be grayed out.
DESIGN:
Basically, the NPSERVER application launches multiple
instances of a server thread. When the application is
started, the first thread is created. It creates an
instance of the server side of the named pipe, and waits for
a client to connect. Once a client connects, another thread
is started and it too blocks waiting for a client.
Meanwhile, the first thread updates a global array of client
information with this specific client's information. The
thread then enters a loop reading from this client. Any
time this specific client sends a message, this server
thread will call a function (TellAll) which will write the
message to all the clients that have been listed in the
global array.
On the client side, NPCLIENT tries to connect to the named
pipe with a CreateFile call. Once it has connected, it
creates a thread which loops and reads any message from the
server side. Once a message is read, it is printed in the
larger edit field. Any time the user hits the Send button,
the main thread grabs any text in the lower edit field, and
writes it to the server.
The steps between NPSERVER and an instance of NPCLIENT looks
like this:
NPSERVER NPCLIENT
-------- --------
CreateNamedPipe()
ConnectPipe() // Blocks
CreateFile() //Connects to pipe.
spawn separate thread to read pipe
return from block
updates array of clients
spawn another server thread
Loop
ReadFile() // Blocks on overlap
WriteFile() // User hits Send.
return from block
WriteFile() // Broadcast to clients
End loop // When client breaks pipe.
ReadPipe Thread:
Loop
ReadFile()
block till server broadcasts
return from block.
put string in edit field.
End loop // when server breaks.
The overlapped structure should be used anytime a pipe is
expected to block for any length of time on a read or write.
This allows the thread to return immediately from a read or
write to service any other part of your application. The
overlapped structure should also be used on a named pipe
anytime you expect to do simultaneous reads and writes.