Previous topic |
Next topic |
Contents |
Contact z/OS |
Library |
PDF
Selecting requests in a concurrent server program z/OS Communications Server: IP Sockets Application Programming Interface Guide and Reference SC27-3660-00 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
At this point in the process, the server is ready to handle requests on this port from any client on a network from which the server is accepting connections. Until this point however, it had been assumed that the server was handling one socket only. Now, an application is not limited to one socket. Typically, a server listens for clients on a particular socket, but it allocates a new socket for each client it handles. For maximum performance, a server should operate only on those sockets ready for communication. The select() call allows an application to test for activity on a group of sockets. To test any number of sockets with one call to select(), place the sockets to test into a bit set, passing the bit set to the select() call. A bit set is a string of bits where each member of the set is represented by 0 or 1. If the members bit is 0, the member is not in the set; if the members bit is 1, the member is in the set. For example, if socket 3 is a member of a bit set, then bit 3 is set; otherwise, bit 3 is cleared. In C language, the following functions are used to manipulate
the bit sets:
If a socket is active, it is ready for read or write data.
If the socket is not active, an exception condition might have occurred.
Therefore, the server specifies three bit sets of sockets in its call
to the select() call as follows:
A server that processes many clients at once can be written to process only those clients that are ready for activity. When all initialization is complete, and the server main
process is ready to enter normal work, it builds a bit mask for a
select() call. The select() call is used to test pending activity
on a list of socket descriptors owned by this process. Before issuing
the select() call, construct three bit strings representing the sockets
you want to test, as follows:
The length of a bit string must be expressed as a number of fullwords. If the highest socket descriptor you want to test is socket descriptor number 3, you must pass a 4-byte bit string, because this is the minimum length. If the highest number is 32, you must pass 8 bytes (2 fullwords). The number of fullwords in each select mask can be calculated
as follows:
Table 1 shows the first fullword passed using a bit string.
Using standard assembler numbering notation, the leftmost bit or byte is relative to 0. If you want to test socket descriptor number 5 for pending read activity, you raise bit 2 in byte 3 of the first fullword (X'00000020'). To test both socket descriptors 4 and 5, raise both bit 2 and bit 3 in byte 3 of the first fullword (X'00000030').To test socket descriptor Number 32, pass 2 fullwords, where the numbering scheme for the second fullword resembles that of the first. Socket descriptor Number 32 is bit 7 in byte 3 of the second fullword. To test socket descriptors Number 5 and Number 32, pass 2 fullwords with the following content: X'0000002000000001'. The bits in the second fullword represent the socket descriptor numbers shown in Table 2.
Subsequent mask words continue this pattern; word 3 for sockets 64-95, word 4 for sockets 96-127, and so on. To set and test these bits in another way, use the following assembler macro, found in file SEZACMAC:
Figure 1. To set/test
bits for SELECT calls
If you develop your program using another programming language, you might be able to benefit from the EZACIC06 routine, which is provided as part of TCP/IP Services. This routine translates between a character string mask (1 byte per flag) and a bit string mask (1 bit per flag). If you use the select() call in COBOL, EZACIC06 can be very useful. Build the three bit strings for the socket descriptors
you want to test, and the select() call passes back three corresponding
bit strings with bits raised for those of the tested socket descriptors
with activity pending. Test the socket descriptors using the following
sample:
In the above select() call, the asynchronous facilities
of the socket assembler macro interface is used. By placing an ECB
parameter on the EZASMI macro call, the select() call does not block
the process; we receive control immediately, even if none of the specified
socket descriptors had activity. Use this technique to enter a wait,
which waits for a series of events of which the completion of a select()
call is just one. In the sample application, the main process was
placed into a wait from which it would return when any of the following
events occurred:
The number of socket descriptors with pending activity is returned in the RETCODE field. You must process all selected socket descriptors before you issue a new select() call. A selected socket descriptor is selected only once. When a connection request is pending on the socket for which the main process issued the listen() call, it is reported as a pending read. When the main process has given a socket, and the subtask has taken the socket, the main process socket descriptor is selected with an exception condition. The main process is expected to close the socket descriptor when this happens. Applications can handle multiple sockets. In such situations,
use the select() call to determine the sockets that have data to be
read, those that are ready for data to be written, and the sockets
that have pending exceptional conditions. An example of how the select()
call is used is shown in Figure 2.
Figure 2. An application using the select() call
In this example, the application uses bit sets to indicate that the sockets are being tested for certain conditions, and also indicates a timeout. If the timeout parameter is NULL, the call does not wait for any socket to become ready. If the timeout parameter is nonzero, the select() call waits for the amount of time required for at least one socket to become ready under the indicated condition. This process is useful for applications servicing multiple connections that cannot afford to block, thus waiting for data on one connection. For a description, see select(). |
Copyright IBM Corporation 1990, 2014
|