Important: The information in this document is obsolete and should not be used for new development.
Sending and Receiving Data: An Overview
To send data, you must address each packet to the socket for which it is intended because you cannot open and maintain a connection between two sockets using DDP. To receive a data packet using DDP, you must provide a socket listener process that DDP associates with the socket that your application uses. When you open the socket for your application to use, you must provide a pointer to the socket listener. DDP associates the address of the socket listener with your application's socket so that the .MPP driver can call your socket listener when it receives a packet that is addressed to your socket-client application. DDP maintains a separate entry in its socket table for each socket and socket listener pair.Applications developers commonly write a single socket-client application that both sends and receives data and that includes a socket listener process to receive data.
To clarify the steps involved in sending and receiving data, this section gives you an overview of these tasks as separate sequences after it explains how to open a socket.
The steps for sending and receiving data refer to sections that are provided later in
this chapter that describe how to
If you want to provide features in addition to the DDP checksum feature to check data and correct errors, you can include them in your application, you can define your own AppleTalk protocol, or you can use a higher-level AppleTalk protocol such as ATP or ADSP instead of calling DDP directly. (For information about DDP checksums, see "Using Checksums" beginning on page 7-19.)
- create a write-data structure, which you need to send data
- use the registers that the .MPP driver uses to pass parameters to your socket listener
- write a socket listener, with sample code illustrating this
To make your application available to other users of AppleTalk, you must use the NBP
PRegisterName
function to register the name that represents your socket-client applica-
tion. When you are finished using the socket, you must use the NBPPRemoveName
function to remove this name from the NBP names table. See the chapter "Name-Binding Protocol (NBP)" in this book for more information about these functions.Opening a Socket
To send and receive data using DDP, your application must first open a socket. Opening a socket makes your application a client of that socket. You open a socket with thePOpenSkt
function. When you open a socket, you must provide a pointer to your socket listener and you must specify 0 for the socket number if you want DDP to dynamically assign a socket.The
POpenSkt
function assigns a socket number to your application and enters the number in the socket table along with the pointer to the socket listener that you provide. ThePOpenSkt
function returns the socket number to you in thesocket
field of the parameter block.
If you do not want DDP to randomly assign a socket number to your application, you can specify the number of a particular socket for DDP to open. For information on the range of socket numbers from which you can select, see "Assigning Socket Numbers" on page 7-6.
- Associating a single socket listener with more than one socket
- If your application includes processes that each have their own sockets, you can assign a single socket listener to more than one socket, but each socket should have its own buffer or set of buffers for receiving data.
When your application is finished using a socket, you must use the
- IMPORTANT
- You cannot specify a
NIL
pointer to the socket listener. If you do,
the system on which your application is running will crash.PCloseSkt
function to close the socket.Sending Data
To send data, you must create a write-data structure that contains the data in a specific format and then call a DDP function to send the data. After you have opened a socket using thePOpenSkt
function, here are the steps that you follow to send data using DDP:
See "Creating a DDP Write-Data Structure" beginning on page 7-12 for information about how to create a write-data structure using the DDP procedure
- Create a write-data structure.
- Use the DDP function
PWriteDDP
to send the data.
BuildDDPwds
or your own code.Packets with long headers can include a checksum that can be used to verify the integrity of the packet data. For information on how to direct DDP to calculate a checksum for data that you want to send, see "Using Checksums" beginning on page 7-19. For details of the contents of a long header, see "The DDP Packet and
Frame Headers" beginning on page 7-14.Receiving Data
To receive data using DDP, you must provide a socket listener that is part of your socket-
client application. The socket listener code must
There are many ways to design and write a socket-client application and socket listener. This chapter offers one possibility. For details of this sample socket listener and for its code, see "A Sample Socket Listener" beginning on page 7-20.
- be written in assembly language because it must read from and write to the
CPU's registers- include buffers to hold the data that it reads
- use the register values that the .MPP driver passes to your socket listener
- determine the type of packet, if you have defined more than one protocol type that your application handles
- if the packet includes a long header, calculate the checksum value, if one is used
To receive data, your application must have already opened a socket using the
- Note
- Your socket-client application should test to find out when the socket listener finishes processing a packet so that the socket-client application can begin its own packet reading and processing.
POpenSkt
function and have passed thePOpenSkt
function a pointer to your
socket listener.Here are the tasks involved in receiving data using DDP:
- The .MPP driver calls your socket listener when it receives a packet addressed to your socket-client application. The .MPP driver passes values to you in the CPU's registers. You need to know how the .MPP driver uses these registers and how you can use them. For information about these registers, see "How the .MPP Driver Calls Your Socket Listener" beginning on page 7-13. One of the values that the .MPP driver passes to you is a pointer to the buffer that holds the DDP packet header. You need
to know how the DDP packet header and the frame header are structured. For information about these headers, see "The DDP Packet and Frame Headers" beginning on page 7-14.- To hold the data that it reads, your socket listener must allocate memory for buffers. In addition to allocating data buffers, either your socket-client application or the socket listener (if you write the socket listener code to carry out this function) must perform some initialization tasks. For information about these tasks and how the sample socket listener handles them, see "Socket Listener Queues and Buffers" beginning on page 7-20, "Setting Up the Socket Listener" beginning on page 7-22,
and "Initializing the Socket Listener" beginning on page 7-24.- When the .MPP driver calls your socket listener, the socket listener must read the incoming packet into one or more data buffers. To do this, the socket listener uses two processes,
ReadPacket
andReadRest
, which are implemented as a single routine
in the hardware driver. The .MPP driver passes you the address of this routine in one of the CPU's registers. For more information, see "Reading an Incoming Packet" beginning on page 7-17.- If you have defined more than one DDP protocol type that your application handles, check the DDP protocol type field of the datagram header (see Figure 7-6 on page 7-15) to determine the protocol type of the packet you have just received.
The AppleTalk internet address (network number, node ID, and socket number) is insufficient to distinguish between packets intended for different processes that are using the same socket. Your socket listener must use some other information (such as the DDP protocol type or a higher-level protocol header imbedded in the DDP packet data) to make this distinction.
- If the packet contains a long header, the socket listener needs to find out if the header contains a checksum. If it does, the socket listener needs to calculate the checksum to determine if the packet's data has been corrupted. For more information, see "Using Checksums" beginning on page 7-19.
- The socket listener can now process the packet or pass it to the client application for processing. The sample socket listener provided here writes the packet buffer to a queue that it uses for successfully processed packets and removes the packet from the queue for incoming packets. For a description of how the sample socket listener does this, see "Processing a Packet" beginning on page 7-25.
- The client application can now read in the packet for its own purposes. The client application should include code that periodically checks to determine whether the socket listener has finished processing an incoming packet. For a description of how the sample socket listener's client application performs this task and some sample code, see "Testing for Available Packets" beginning on page 7-31.