Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Networking /
Chapter 6 - AppleTalk Transaction Protocol (ATP) / Using ATP


Writing a Requester ATP Application

You use the PSendRequest function or the PNSendRequest function to send an ATP request to another socket.

Before you can use ATP, you must first open the .MPP driver, which in turn opens the .ATP driver. Use the Device Manager's OpenDriver function to open the .MPP driver. Even if you suspect that the .MPP and the .ATP drivers are open, you should call
the OpenDriver function for the .MPP driver to ensure that this is the case. Calling OpenDriver for a driver that is already open will not produce harmful repercussions. See the chapter "Device Manager" in Inside Macintosh: Devices for information on
the OpenDriver function. Do not close the .MPP driver when you are finished using ATP because other applications dependent on it or on the .ATP driver require that it
remain open.

To send an ATP request, follow these steps:

  1. Create a buffer data structure (BDS) to hold the data that you expect to receive in response to your request. For information on how to do this, see "Creating a Buffer Data Structure" on page 6-12.
  2. To allow ATP to assign the socket to be used to send the request, use the PSendRequest function. To specify a particular socket to be used to send the request, use the PNSendRequest function; in this case, you must call POpenATPSocket to first open the socket (see "POpenATPSkt" on page 6-30 for information about this function). For information on the parameters required for these functions, see "Specifying the Parameters for the Send Request Function" on page 6-12.
  3. You can get the transaction ID that ATP assigns to a request from the reqTID parameter; you need this ID to cancel a request. However, before you check this
    field, make sure that the valid transaction ID (atpTIDValidvalue) bit (bit 1) of
    the atpFlags parameter is set. ATP sets this bit to inform you that it has assigned
    a transaction ID and that the reqTID field is now valid.
  4. If you opened a socket to be used for the PNSendRequest call, close the socket using PCloseATPSkt. See"PCloseATPSkt" on page 6-31 for information on how to use this function. If you use the PSendRequest function, ATP allocates a socket and opens and closes it for you.

The code in Listing 6-1 shows how to open a socket and issue a call to the PSendRequest function. The code uses the BuildBDS function to create a buffer data structure to
hold the response data it expects in response. This segment of code assumes that the application has already called the OpenDriver function to open the .MPP and
.ATP drivers.

Listing 6-1 Opening a socket and sending an ATP request

CONST
   kMaxPacketSize = 578;            {maximum packet size we can receive}
   kNRespBuffs = 8;                 {you allow eight response buffers}
   kOurRespBufSize = kMaxPacketSize * kNRespBuffs;
                                    {response buffer size}
VAR
   err:           OSErr;
   reqLength:     Integer;
   nBufs:         Integer;
   ref:           Integer;
   targetAddr:    AddrBlock;
   gAtpPBPtr:     ATPPBPtr;
   gReqBufPtr:    Ptr;
   gRespBufPtr:   Ptr;
   gSRespBdsPtr:  BDSPtr;
BEGIN
   gAtpPBPtr := ATPPBPtr(NewPtr(SizeOf(ATPParamBlock)));
   gReqBufPtr := NewPtr(kMaxPacketSize);
   gRespBufPtr := NewPtr(kOurRespBufSize);
   gSRespBdsPtr := BDSPtr(NewPtr(SizeOf (BDSType)));
   err := OpenDriver('MPP',ref);
   if err <> noErr THEN DoErr(err);
   WITH gAtpPBPtr^ DO

   BEGIN
      atpSocket := 0;                  {dynamically allocate a socket}
      addrBlock.aNet := 0;             {accept requests from anyone}
      addrBlock.aNode := 0;
      addrBlock.aSocket := 0;
   END;
   err := POpenATPSkt(gAtpPBPtr,false);{socket is returned in }
                                       { gAtpPBPtr^.atpSocket}

   IF err <> noErr THEN DoErr(err);
   IF gAtpPBPtr^.ioResult <> noErr THEN DoErr(err);

   MyPrepareRequestData(gReqBufPtr,@reqLength);
                                       {user routine that prepares the }
                                       { request data to be sent}
   MyLocateTargetAddress(@targetAddr);
                                       {user routine that locates the }
                                       { target machine}
   {Set up your BDS structure.}
   nBufs := BuildBDS(gRespBufPtr,Ptr(gSRespBdsPtr),kOurRespBufSize);

   WITH gAtpPBPtr^ DO
   BEGIN
      atpFlags := atpXOvalue;          {issue an exactly-once transaction}
      addrBlock.aNet := targetAddr.aNet;
                                       {set up the target machine}
      addrBlock.aNode := targetAddr.aNode;
      addrBlock.aSocket := targetAddr.aSocket;
      reqLength := reqLength;          {size of your request data}
      reqPointer := gReqBufPtr;        {pointer to actual request data}
      numOfBuffs := nBufs;             {number of responses expected}
      bdsPointer := Ptr(gSRespBdsPtr); {your BDS pointer}
      timeOutVal := 3;                 {timeout interval}
      retryCount := 5;                 {number of retries}
   END;
   err := PSendRequest(gAtpPBPtr,false);
   IF err <> noErr THEN DoErr(err);

   MyProcessResponses(gAtpPBPtr^.bdsPointer,gAtpPBPtr^.numOfResps);
                                       {user routine to process the }
                                       { response data returned}
   
   {Clean up after you are done.}
   DisposePtr(Ptr(gAtpPBPtr));
   DisposePtr(gReqBufPtr);
   DisposePtr(gRespBufPtr);
   DisposePtr(Ptr(gSRespBdsPtr));
END.

Creating a Buffer Data Structure

Response data can comprise up to eight packets. ATP uses the organization of the buffer data structure (BDS) to manage these packets and ensure their complete delivery. The BDS must be an array of up to eight elements. You can create the buffer data structure yourself, or you can use the BuildBDS function for this purpose. You pass BuildBDS a pointer to a buffer and the length of the buffer, and it creates up to eight elements, one for each packet, depending on the size of the buffer that you supply. BuildBDS returns as its function result the number of elements that it creates; you pass this number and a pointer to the buffer data structure to the PSendRequest or PNSendRequest function that you call to issue the request. The memory that you allocate for the buffer must be nonrelocatable until the PSendResponse call completes execution. After PSendResponse returns, you should release this memory if you do not intend to reuse it.

Specifying the Parameters for the Send Request Function

When you call either the PSendRequest function or the PNSendRequest function to send an ATP request, you must do these tasks:

You can send up to 4 bytes of additional information in the userData parameter,
and ATP will pass this to the responder application in the userData parameter of its PGetRequest call. To make this parameter meaningful, both the requester and the responder applications should agree on the use of these additional data bytes that are separate from the request or response data sent in an ATP transaction.

Setting the Timeout and Retry Count Parameters

When a transaction does not complete on the first transmission, ATP retries it a number of times. You can control ATP's retry behavior by setting these two parameters: the timeOutVal field and the retryCount field. The timeOutVal value determines
in seconds how long ATP waits before resending the original request packet; the retryCount value determines how many times ATP retries to send the request.

ATP optimizes how it performs retries based on the response bitmap; ATP on the requester side resends the request with the header bitmap indicating to the ATP driver on the responder side which packets it should resend. (See the "The Bitmap/Sequence Number" on page 6-6 for more information.) ATP makes this request to resend until it receives all of the packets or it exhausts the number of retry attempts that you specify. If ATP exhausts all of the retry attempts before the requester side receives all of the packets, ATP returns an error.

To choose the correct timeout value and retry count combination, you should consider the speed and complexity of your network--for example, take into account the degree of traffic congestion and whether your network contains multiple routers. You can use the AppleTalk Echo Protocol (AEP) echo socket to test the network performance and adjust the values accordingly. For more information about using the AEP echo socket to test network performance, see the chapter "Datagram Delivery Protocol (DDP)" in this book. You can store various pairs of values in a preferences resource file so that you can easily change them to adapt to the speed of the network.

If you want ATP to retry indefinitely to send the request, you can set the retryCount parameter to 255. In this case, ATP will send the request repeatedly until either the ATP responder end satisfies the request and sends back a response or you cancel the request. To cancel a PSendRequest call, you can use either the PKillSendReq function or the PRelTCB function. To cancel a PNSendRequest call, you can use the PKillSendReq function only.

Setting the Release Timer Value

For exactly-once transactions, the ATP responder code saves the response packets until the ATP code on the requester side indicates that it has received all of them. When this is the case, the ATP code on the requester side sends a transaction release packet to tell the ATP code on the responder side to release the response packets. Because this packet could be dropped or lost during transmission, ATP uses a release timer to discard the retained packets after a specified amount of time and to release the memory used to
store them.

If the nodes at both ends of the ATP connection are running AppleTalk Phase 2
drivers, you can control the release timer value that determines when ATP releases
the response packets by setting the 3 lower bits of the TRelTime parameter to one
of the following values:
TRelTimeSetting of
release timer
00030 seconds
0011 minute
0104 minutes
1008 minutes


Previous Book Contents Book Index Next

© Apple Computer, Inc.
7 JUL 1996