The bottom-level interface to RPC enables the application to control all options. clnt_tli_create() and the other expert-level RPC interface routines are based on these routines. You rarely use these low-level routines.
Bottom-level routines create internal data structures, buffer management, RPC headers, and so on. Callers of these routines, like the expert-level routine clnt_tli_create(), must initialize the cl_netid and cl_tp fields in the client handle. For a created handle, cl_netid is the network identifier (for example, udp) of the transport and cl_tp is the device name of that transport (for example, /dev/udp). The routines clnt_dg_create() and clnt_vc_create() set the clnt_ops and cl_private fields.
The following code example shows calls to clnt_vc_create() and clnt_dg_create().
/*
* variables are:
* cl: CLIENT *
* tinfo: struct t_info returned from either t_open or t_getinfo
* svcaddr: struct netbuf *
*/
switch(tinfo.servtype) {
case T_COTS:
case T_COTS_ORD:
cl = clnt_vc_create(fd, svcaddr,
prog, vers, sendsz, recvsz);
break;
case T_CLTS:
cl = clnt_dg_create(fd, svcaddr,
prog, vers, sendsz, recvsz);
break;
default:
goto err;
}
These routines require that the file descriptor be open and bound. svcaddr is the address of the server.
The following code example is an example of creating a bottom-level server.
/*
* variables are:
* xprt: SVCXPRT *
*/
switch(tinfo.servtype) {
case T_COTS_ORD:
case T_COTS:
xprt = svc_vc_create(fd, sendsz, recvsz);
break;
case T_CLTS:
xprt = svc_dg_create(fd, sendsz, recvsz);
break;
default:
goto err;
}