These multithreaded send and receive TPs are more advanced than the single-threaded equivalents. The samples located in the MSENDRCV subdirectory all use the asynchronous interface of APPC, with verb completion signaled by events (WinAsyncAPPCEx). These TPs show how to code multithreaded APPC applications with multiple conversations per thread. They are more complex than the single-threaded equivalents, but are also more realistic.
If you are unfamiliar with APPC, examine the single-threaded TPs first. If you are unfamiliar with methods of creating threads or processing events in Microsoft® Windows NT® and Microsoft® Windows® 95, see the Microsoft® Platform SDK documentation along with the multithreaded TPs.
There are three multithreaded send and receive routines:
To set up these TPs, create an appropriate APPC LU-LU-mode triplet. The default is SENDLU-RECVLU-#INTER, but this can be configured (see the sections that follow). To run a large number of simultaneous conversations, increase the session limits for #INTER or use another mode with large session limits.
One obvious way of configuring these programs is to configure MSEND to run with MRCV; another way is to configure MSENDRCV to run with another copy of MSENDRCV. However, you can also configure MSEND to run with one or more copies of RECVTP (the single-threaded version) and MRCV to run with one or more copies of SENDTP. You can also configure MSENDRCV to run with MSEND, MRCV, SENDTP or RECVTP. For more information, see the sections that follow.
One possible arrangement is to place SENDTP (single-threaded) on multiple client computers, and configure MRCV (multithreaded) on a server so that it interacts with all the TPs on the clients. Many other arrangements are possible.
Each TP uses a configuration file for input. To name the file, use .CFG as the extension, and use the same base file name and directory location as the executable file (the TP itself).
The following table shows examples of CFG files that could be used with MSEND and MRCV.
Example of MSEND.CFG file | Example of MRCV.CFG file |
---|---|
ResultFile=MSEND.OUT |
TraceFile=MRCV.TRC |
TraceFile=MSEND.TRC |
LocalTPName=MRCVTP |
RemoteTPName=MRCVTP |
NumRcvConvs=32 |
LocalLUAlias=LUA |
NumRcvThreads=4 |
RemoteLUAlias=LUB |
RcvSize=4096 |
ModeName=#INTER |
|
NumSendConvs=32 |
|
NumSends=128 |
|
ConfirmEvery=16 |
|
SendSize=256 |
For MSEND, the configuration file (MSEND.CFG) can contain the following items, one per line, in any order. If a variable is not found in the file or the file is not present at all, the default is used.
Line | Default value | Value to supply |
---|---|---|
ResultFile = |
MSEND.OUT | File name to print timings to (located in default directory for MSEND) |
TraceFile = |
MSEND.TRC | Trace file name (located in default directory for MSEND) |
LocalLUAlias = |
SENDLU | Local LU alias |
RemoteLUAlias = |
RECVLU | Remote LU alias |
ModeName = |
#INTER | Mode name |
RemoteTPName = |
MRCVTP | Name of remote TP (for MC_ALLOCATE) |
NumSendConvs = |
4 | Number of conversations to send |
NumSends = |
8 | Number of MC_SEND_DATA verbs per conversation |
SendSize = |
256 | Size in bytes of data sent each time |
ConfirmEvery = |
2 | Number of MC_SEND_DATA verbs between MC_CONFIRM verbs |
The following lines are for MRCV:
Line | Default value | Value to supply |
---|---|---|
TraceFile = |
MRCV.TRC | Trace file name (located in default directory for MSEND) |
LocalTPName = |
MRCVTP | Name of local TP (for RECEIVE_ALLOCATE) |
NumRcvConvs = |
4 | Number of conversations to receive |
NumRcvThreads = |
2 | Number of threads to start for processing receive conversations |
RcvSize = |
4096 | Size in bytes of receive buffer for MC_RECEIVE_AND_WAIT |
The following table shows examples of configuration files (MSENDRCV.CFG) that could be used with MSENDRCV. Each row of the table (Example A and Example B) contains two files that work together on a pair of computers.
Example A of MSENDRCV.CFG | Example B of MSENDRCV.CFG |
---|---|
ResultFile=MSENDRCV.OUT |
ResultFile=MSENDRCV.OUT |
TraceFile=MSENDRCV.TRC |
TraceFile=MSENDRCV.TRC |
LocalTPName=TPA |
LocalTPName=TPB |
RemoteTPName=TPB |
RemoteTPName=TPA |
LocalLUAlias=LUA |
LocalLUAlias=LUB |
RemoteLUAlias=LUB |
RemoteLUAlias=LUA |
ModeName=#INTER |
ModeName=#INTER |
NumRcvConvs=50 |
NumRcvConvs=25 |
NumRcvThreads=4 |
NumRcvThreads=4 |
RcvSize=4096 |
RcvSize=4096 |
NumSendConvs=25 |
NumSendConvs=50 |
NumSends=100 |
NumSends=100 |
ConfirmEvery=10 |
ConfirmEvery=10 |
SendSize=256 |
SendSize=256 |
The following lines are for MSENDRCV:
Line | Default value | Value to supply |
---|---|---|
ResultFile = |
MSENDRCV.OUT | File name to print timings to (located in default directory for the MSEND or MSENDRCV sending TP) |
TraceFile = |
MSENDRCV.TRC | Trace file name (located in default directory for the MSEND or MSENDRCV sending TP) |
LocalLUAlias = |
SENDLU | Local LU alias |
RemoteLUAlias = |
RECVLU | Remote LU alias |
ModeName = |
#INTER | Mode name |
RemoteTPName = |
MRCVTP | Name of remote TP (for MC_ALLOCATE) |
NumSendConvs = |
4 | Number of conversations to send |
NumSends = |
8 | Number of MC_SEND_DATA verbs per conversation |
SendSize = |
256 | Size in bytes of data sent each time |
ConfirmEvery = |
2 | Number of MC_SEND_DATA verbs between MC_CONFIRM verbs |
LocalTPName = |
MRCVTP | Name of local TP (for RECEIVE_ALLOCATE) |
NumRcvConvs = |
4 | Number of conversations to receive |
NumRcvThreads = |
2 | Number of threads to start for processing receive conversations |
RcvSize = |
4096 | Size in bytes of receive buffer for MC_RECEIVE_AND_WAIT |
The output from MSEND and MSENDRCV consists of details of the configuration and the time taken for each conversation, and is sent to the result file specified in MSEND.CFG or MSENDRCV.CFG.
These TPs use Windows NT- or Windows 95-based multiple event processing to avoid creating an unnecessary number of threads.
The TPs also use Windows-based processing, but this is incidental. Its only purpose is to display beneath the icon on the screen a running count of threads, the number of conversations currently sending or receiving data, and the number of conversations completed. The Windows-based processing could easily be removed to create a completely batch-oriented program. To do this, termination would need to be signaled with an event rather than with WM_CLOSE.
The TP name used in TP_STARTED is the name of the executable file (MSEND, MRCV, or MSENDRCV). The TP names used in MC_ALLOCATE and RECEIVE_ALLOCATE can be configured, as shown in the preceding tables.
MSEND reads its configuration file (or uses defaults) to determine the number of send conversations to start. Each conversation reads the value of NumSends (or uses the default), issues that number of MC_SEND_DATA verbs, and then terminates. When all of the conversations for a thread have terminated, the thread itself terminates. When all of the send threads have terminated, the program terminates.
An MC_CONFIRM verb is issued before the first MC_SEND_DATA and then at the intervals specified by ConfirmEvery. The complete data flow for a conversation is as follows:
TP_STARTED
MC_ALLOCATE
MC_CONFIRM
MC_SEND_DATA (repeated the number of times specified by ConfirmEvery)
MC_CONFIRM
MC_SEND_DATA (repeated the number of times specified by ConfirmEvery)
MC_CONFIRM
(Pattern repeats until the number of MC_SEND_DATA verbs equals NumSends.)
MC_DEALLOCATE
TP_ENDED
MRCV starts up an initial thread for issuing RECEIVE_ALLOCATE verbs, then reads its configuration file (or uses defaults) to determine the number of receive threads to start and the number of conversations to receive.The initial thread issues a RECEIVE_ALLOCATE and waits. When the RECEIVE_ALLOCATE completes, the initial thread turns the processing of the conversation over to the next available receive thread, and issues another RECEIVE_ALLOCATE. This process continues until the configured number of RECEIVE_ALLOCATE verbs (that is, NumRcvConvs) have completed.
There is a limit to the number of conversations that can be supported on a thread, because of the limit to the number of events that can be waited for with WaitForMultipleObjects (a function in the Win32® API). For send threads, the limit is 64 conversations per thread; for receive threads, the limit is 63 conversations per thread.
MSEND works with this limit by starting enough threads to support the configured number of conversations. For example, if NumSendConvs is set to 200, four send threads are started: three of them process 64 conversations each and one processes the remaining eight conversations.
MRCV works with this limit by comparing NumRcvConvs to NumRcvThreads. If NumRcvConvs is more than (63 * NumRcvThreads), NumRcvThreads is increased. If NumRcvThreads is greater than NumRcvConvs, NumRcvThreads is reduced to prevent creating unneeded threads.
With MRCV, to ensure that a receive thread correctly picks up the conversation, two special events are used per thread: event1 and event2. The following table illustrates their use.
RECEIVE_ALLOCATE thread | Receive thread |
---|---|
Issue RECEIVE_ALLOCATE and wait | Wait on event1 |
(RECEIVE_ALLOCATE completes) | |
Select next receive thread and set event1 for that thread; then wait on event2 for that thread |
|
(Event1 completes) | |
Add conversation to list of conversations being processed | |
Set event2 | |
(Event2 completes) | |
REPEAT | REPEAT |
The receive thread waits not only on the event1 set for it, but also on one event for each conversation the thread is processing.
If NumRcvConvs is set to zero, the RECEIVE_ALLOCATE thread will never terminate. If NumSends is set to zero, the conversation will never terminate; this is useful for getting the maximum number of simultaneous conversations.
If you want to observe the detailed processing of these TPs, you can enable tracing. To do this, find the following line, commented out, near the top of the file:
#define SRTRC
Enable this line, and trace statements will be written to the trace file(s) specified by the TraceFile variable.
There are also some trace statements that have been commented out. If they are left commented out, only MC_CONFIRM and MC_CONFIRMED processing is traced while a conversation is running, to maintain a send or receive count without generating a large amount of trace information. You can activate the detailed tracing of events (such as the sending of data) by enabling one or more trace statements.
The snatrace utility provides APPC API tracing (for SNA applications). For more information about the snatrace utility, see the Microsoft SNA Server Administration Guide.