|
|
The TLI provides users with automatically allocated transport addresses under certain circumstances. That is, it is possible to open and set up a TSAP and use it without your program ever knowing or needing to deal with its own transport address. However, to establish a connection with a particular program, or to send a datagram to a particular program, it is necessary to know that program's transport address. Likewise, if a program is to be written to accept incoming requests to connect to it, or if it is to receive datagrams, then it must be set up so its transport address can be ``known'' by other programs on the network. Because transport addresses are inherently specific to a given transport protocol environment, they must be specific to a particular transport provider.
With TCP/IP, this problem is relatively simple; the address structure used is the same as that used with the socket library. That is, the structure that holds a transport address is the struct sockaddr_in defined in the <netinet/in.h> header file. This structure is not passed as a parameter directly to the TLI functions such as t_bind that use transport addresses; rather, the TLI-defined structures contain a member that is itself a structure of a type called struct netbuf, which contains a pointer to a transport-provider-specific address structure. This pointer points to an object defined as a struct sockaddr_in.
For example, consider this program fragment using the t_bind function:
... #include <sys/tiuser.h> ... struct t_bind *bindreq; static struct sockaddr_in myaddr = { AF_INET, 0, 531 }; struct sockaddr_in *inetaddr;... bindreq = (struct t_bind *)t_alloc(listen_fd, T_BIND, T_ALL); ... /* allow 1 pending incoming connect request */ bindreq->qlen = 1; inetaddr = (struct sockaddr_in *)(bindreq->addr.buf); /* copy our address into the t_bind structure */ *inetaddr = myaddr; bindreq->addr.len = sizeof (struct sockaddr_in); bindreq->addr.maxlen = bindreq->addr.len;
t_bind(listen_fd, bindreq, bindreq); ...
Notice that the structure defined by the type struct t_bind is
the same as that defined for TLI. However, the pointer found in
bindreq->addr.buf
, defined as char *,
points to the
area where the transport address is stored, which is used as an area
of the type struct sockaddr_in. Notice also that the correct amount
of space is allocated for that region by the t_alloc function,
because the t_open function obtains information on the maximum
address size (even if the user does not make use of that information).
This example can be generalized to the cases that occur in the other TLI functions. The cases are not described in detail here, but occur for the functions t_accept, t_bind, t_connect, t_listen, t_rcvconnect, t_rcvudata, t_rcvuderr, t_snddis, and t_sndudata, and they apply to argument structures passed to these functions. In all cases, the argument structure contains an element that is a structure declared as, for example, struct netbuf addr.
There are some additional important semantics relating to the structure struct sockaddr_in. The transport addresses stored in these structures have two parts of interest: the IP address of the host and a port number representing a TSAP on that host. In cases where the transport address in question is on the same host as the program doing the TLI call (that is, for its own address), the IP address can be left as 0, as in the example program fragment above. Thus, programs that must have a known address need only have their port number hard-coded; the host address coded as 0 works on any system. Conversely, programs that need to connect to a server program using this technique need to know the hostIP address of the host where this program is running.
Also, programs that need to have a port number dynamically
allocated can code the port number as 0.
The same functionality is provided in other
ways with TLI (that is, by
passing a NULL pointer
to the t_bind call or by setting the
address length field in the address struct netbuf to 0).