#include "spx_app.h"int t_bind ( int spxFd, struct t_bind *req, struct t_bind *ret )
spxFd
req
req
to NULL to obtain a dynamic socket (qlen is assumed to be zero).
ret
ret
is pointing.
If the application does not care to which address it was bound, it can set ret to NULL.
ret
This function works as specified in ``Programming with the X/Open Transport Interface (XTI)'' with the additions explained below.
The t_bind structure has the following format:
struct t_bind { netbuf addr; unsigned qlen; };The
qlen
field is used to indicate the total number of outstanding connection requests allowed on this endpoint.
The netbuf structure has the following format:
struct netbuf { unsigned int maxlen; unsigned int len; char *buf; };For a t_bind call, a pointer to an ipxAddr_t structure must be passed in the
req.addr.buf
field to bind to a static socket. If binding to a dynamic socket, a NULL pointer can be passed.
The ipxAddr_t structure has the following format:
typedef struct ipxAddress{ uint8 net[4]; uint8 node[6]; uint8 sock[2]; } ipxAddr_t;The t_bind call allows an endpoint to bind to a socket number, which can be either dynamic or static. SPX keeps track of which socket number is bound to which transport endpoint.
net
and node
fields do not need to be filled in the ipxAddr_t structure, but the sock field must be initialized to either a static or dynamic socket value.
Static Socket Numbers
Services written to run over SPX/SPXII generally have well-known or static socket numbers associated with them. (Again, contact Novell to obtain an assignment for a static socket number for your application.) By having static socket numbers, SPX/SPXII users can be sure that their server and client application types match.
To bind to a static socket number, complete the following steps.
req
and ret
. They can be the same structure.
req.addr.buf
field must point to the ipxAddr_t structure allocated in Step 1.
If the socket number desired is not currently being used by another IPX/SPX user, the SPXII driver returns the local network address, local node address, and the allocated or requested socket number in the corresponding fields of the ipxAddr_t structure of the ret.addr.buf
field.
Only one IPX/SPX endpoint can bind to a given socket number at a time. If the user tries to bind to a socket that has already been bound to, an error results and the bind fails.
Another method to coordinate servers and clients is to use the Service Advertising Protocol (SAP). For programming information, see Chapter 8, "SAP Library," on page 233. Dynamic Socket Number Two methods can be used to have the SPXII driver allocate and assign a dynamic socket number.
The qlen field in the t_bind structure indicates to SPXII the total number of outstanding connection requests allowed on this transport endpoint.
SPXII allows up to a specified number of outstanding connection requests per transport endpoint. This is currently set to 5. Even if the UNIX application requests more than 5, only 5 are given.
Although you are allowed to have more than one outstanding connection request, we recommend that you have only one.
If a value greater than 1 is specified in the qlen
field during a t_bind, a connection request can arrive from a remote transport endpoint, making the t_listen unblock.
If another connection request arrives between the time the t_listen unblocks and the t_accept is issued, the t_accept fails, saying that an event has occurred. You will not be able to t_accept the connection requests until all pending connection requests have been retrieved from the stream head using t_listen. A t_bind with qlen
equal to 1 should be issued to avoid this outcome.
Example 1 shows how to bind to a dynamic socket, while Example 2 shows how to bind to a specific or static socket number.
/* Bind to dynamic socket. I don't want know what address I am ** bound to. */ { ... if ((t_bind(spxFd, NULL, NULL)) < 0) { t_error("t_bind failed"); exit(-1); } ... }
/* This example shows how to bind to the specific socket 0x4500. ** The SPXII driver fills in the net, node fields of the IPX address, ** and returns the full address. *//* ** Bind to static socket 0x4500; then print full address after t_bind. */
#define SOCKET_TO_BIND_HIGH 0x45 #define SOCKET_TO_BIND_LOW 0x00 { int spxFd; struct t_bind *bind_req; struct t_bind *bind_ret; ipxAddr_t *ipxAddr; ...
/* ** Allocate structures for t_bind request */
if ((bind_req = (struct t_bind *)t_alloc(spxFd, T_BIND, T_ALL)) == NULL ) { t_error("t_alloc of T_BIND request structure failed"); exit(-1); }
/* ** Allocate structures for t_bind return values */
if ((bind_ret = (struct t_bind *)t_alloc(spxFd, T_BIND, T_ALL)) == NULL ) { t_error( "t_alloc of T_BIND return structure failed"); exit(-1); }
/* ** qlen 0 for clients, 1-5 for servers. qlen is the # of ** outstanding connect indications allowed. */
bind_req->qlen = 0; bind_req->addr.len = sizeof(ipxAddr_t); ipxAddr = (ipxAddr_t *)bind_req->addr.buf; ipxAddr->sock[0] = SOCKET_TO_BIND_HIGH; ipxAddr->sock[1] = SOCKET_TO_BIND_LOW;
if (t_bind(spxFd, bind_req, bind_ret) < 0) { t_error( "t_bind failed"); exit(-1); }
/* ** Print t_bind returned values */
fprintf(stderr,"\nt_bind returned:\n");
/* qlen */ fprintf(stderr,"\t%4d for qlen from %s\n", bind_ret->qlen, spxDev);
/* number of address bytes returned */ fprintf(stderr,"\t%4d bytes of address from %s\n", bind_ret->addr.len, spxDev); ipxAddr = (ipxAddr_t *)bind_ret->addr.buf;
/* network */ fprintf(stderr,"\tBound to address:\n\t net 0x%02X%02X%02X%02X\n", ipxAddr->net[0],ipxAddr->net[1],ipxAddr->net[2],ipxAddr->net[3]);
/* node */ fprintf(stderr,"\t node 0x%02X%02X%02X%02X%02X%02X\n", ipxAddr->node[0],ipxAddr->node[1],ipxAddr->node[2], ipxAddr->node[3],ipxAddr->node[4],ipxAddr->node[5]);
/* socket */ fprintf(stderr,"\t socket 0x%02X%02X\n", ipxAddr->sock[0], ipxAddr->sock[1]);
/* ** free structures used for t_bind */
t_free((char *)bind_req, T_BIND); t_free((char *)bind_ret, T_BIND); ... }
After an unsuccessful bind, the state is T_UNBND unless t_error was TOUTSTATE.