Article View: comp.unix.programmer
Article #369RPC: clnttcp_create doesn't work
From: Wade Guthrie
Date: Fri, 07 Aug 1992 02:40
Date: Fri, 07 Aug 1992 02:40
430 lines
11620 bytes
11620 bytes
I am having problems making an RPC call from a client using 'clnttcp_create'
(clnt_perrno says: "RPC: unable to send"). The same code seems to work,
however, when I use 'clnt_create' (I know, "then use clnt_create" :-> -- I
can't). I am on a Sun Sparc IPX running SunOS 4.1.2.
I boiled the RPC code down to the minimum set (I tried to make it COMPLETE,
however, so that it could be cut and compiled). I started with the code
that follows, below.
In the code, note that 'server' needs to be called first. Next, client
wants as a single argument either:
1) when TCP_CLIENT is defined: the internet address followed by the port
address in decimal (and separated by a '.') as in:
prompt> client 129.172.208.239.10.70
where 1070 is the decimal value of the port. It's a bit ugly, but it
was easy to kludge up.
2) when TCP_CLIENT isn't defined: the name of the server, as in:
prompt> client drexler
--- client.c -----------------------------
#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/time.h>
#include "awesome.h"
#define MAIN_ROUTINE 1
#include "rpc_stuff.h"
static CLIENT *client = NULL;
void back_prog_1();
main(argc, argv)
int argc;
char *argv[];
{
# define FUNCTION "main: client"
int argument = ~0;
(void) gethostname (host, sizeof (host));
fprintf (stderr, "%s:%s\n", host, FUNCTION);
# ifdef TCP_CLIENT
client = setup_tcp_client (argv[1], THERE_PROG, THERE_VER);
# else
client = setup_as_client (argv[1], THERE_PROG, THERE_VER);
# endif
/* Make the actual function call */
argument = 42; /* well, it'll do for now */
fprintf (stderr, "%s: calling call_server_1(%d)\n", FUNCTION, argument);
call_server_1 (&argument, client);
if (client != NULL)
clnt_destroy (client);
}
--- server.c -----------------------------
#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#define MAIN_ROUTINE 1
#include "awesome.h"
#include "rpc_stuff.h"
void there_prog_1();
main()
{
# define FUNCTION "main: server"
u_short port;
struct hostent *hostent;
fprintf (stderr, "--%s--\n", FUNCTION);
(void) gethostname (host, sizeof(host));
hostent = gethostbyname (host);
printf("port addr = %d.%d.%d.%d\n",
(unsigned char) (*hostent->h_addr_list)[0],
(unsigned char) (*hostent->h_addr_list)[1],
(unsigned char) (*hostent->h_addr_list)[2],
(unsigned char) (*hostent->h_addr_list)[3]);
port = register_as_server (THERE_PROG, THERE_VER, there_prog_1);
printf("port=%d (0x%04x)\n", port, port);
svc_run (); /* poll for RPC service requests */
fprintf (stderr, "** svc_run returned (and shouldn't have)\n");
exit(1);
}
void *
call_server_1 (arg)
int *arg;
{
long *result;
int argument;
printf ("--%s(%d)--\n", "call_server_1", *arg);
fflush (stdout);
return (NULL);
}
--- rpc_stuff.c --------------------------
#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h> /* for timer stuff */
#include <signal.h>
#include <sys/time.h>
#include "rpc_stuff.h"
CLIENT *
setup_as_client (server, program, version)
char *server; u_long program; u_long version;
{
# define FUNCTION "setup_as_client"
enum ExitCodes {BAD_LINK=1, NO_TIMEOUT };
CLIENT *client;
int argument;
int bad_link = NO;
/* body of the function */
fprintf (stderr, "%s:%s> Link w/server (%s)...", host, FUNCTION, server);
while ( (client=clnt_create (server, program, version, "tcp")) == NULL)
{
clnt_pcreateerror (server);
exit (BAD_LINK);
}
fprintf (stderr, "GOOD link\n");
return client;
}
u_short
register_as_server (program, version, func)
u_long program; u_long version; void (*func)();
{
# undef FUNCTION
# define FUNCTION "register_as_server"
register SVCXPRT *transp;
/* body of the function */
fprintf (stderr, "%s:%s> Entering\n", host, FUNCTION);
(void) pmap_unset (program, version);
transp = svctcp_create(RPC_ANYSOCK, 0, 0);
if (transp == NULL) {
fprintf(stderr, "** %s:%s> Cannot create tcp service.",
host, FUNCTION);
exit(1);
}
if (!svc_register(transp, program, version, func, IPPROTO_TCP)) {
fprintf(stderr, "** %s:%s> Unable to register (%s, %s, tcp).",
host, FUNCTION, program, version);
exit(1);
}
return transp->xp_port;
}
/*
* this thing strips out the port-id from a 'port_id' structure and
* returns a short (for use in a struct sockaddr_in)
*/
static u_short
peel_portid (port)
char *port;
{
static union
{
u_short value;
char bytes[sizeof(u_short)];
}un;
int i = ~0;
un.value = ((unsigned) port[4]*100) + (unsigned) port[5];
printf ("port=%d, 0x%04x\n", (unsigned) un.value, (unsigned) un.value);
return un.value;
}
/*
* this thing strips out the internet addres from a 'port_id'
* structure and returns a short (for use in a struct sockaddr_in)
*/
static u_long
peel_addr (port)
char *port;
{
static union
{
u_long value;
char bytes[sizeof(u_long)];
}un;
int i = ~0;
for(i=0; i<sizeof(u_long); i++)
un.bytes[i] = port[i];
printf("inet address: 0x%08x\n", un.value);
return un.value;
}
CLIENT *clnttcp_create ();
CLIENT *
setup_tcp_client (port_char, program, version)
char *port_char;
u_long program;
u_long version;
{
# undef FUNCTION
# define FUNCTION "setup_tcp_client"
enum ExitCodes {BAD_LINK=1, NO_TIMEOUT };
struct sockaddr_in server_addr;
struct hostent *host_struct;
CLIENT *client = NULL;
int argument = ~0,
bad_link = NO,
port_id = ~0,
i = ~0;
char port_num[6];
/* body of the function */
/*
* peel out the address and port based on the command line --
* the port number is split with a '.' to make the parsing
* just a little easier.
*/
port_num[0] = atoi(strtok(port_char, "."));
port_num[1] = atoi(strtok(NULL, "."));
port_num[2] = atoi(strtok(NULL, "."));
port_num[3] = atoi(strtok(NULL, "."));
port_num[4] = atoi(strtok(NULL, "."));
port_num[5] = atoi(strtok(NULL, "."));
for (i=0; i<6; i++)
printf("%u ", (unsigned char) port_num[i]);
printf("\n");
/* fill the server_address structure */
host_struct = gethostbyaddr ((char *)port_num, 4, AF_INET);
server_addr.sin_addr.s_addr = peel_addr(port_num);
port_id = peel_portid(port_num);
server_addr.sin_port = port_id;
server_addr.sin_family = AF_INET;
fprintf (stderr, "%s:%s> Server is %s = %s\n",
host, FUNCTION,
host_struct->h_name, /* server name */
inet_ntoa(&server_addr.sin_addr.s_addr) /*server address*/);
fprintf (stderr, "%s:%s> TCP Link w/server...", host, FUNCTION);
/*
* copy over the dummy arguments -- I'd expect a bus error if this
* is the prob
*/
while ( (client = clnttcp_create (
&server_addr, program, version, &port_id,
(u_int) 0, (u_int) 0)) == NULL)
{
clnt_pcreateerror ("remote server");
exit (BAD_LINK);
}
fprintf (stderr, "GOOD link\n");
return client;
}
--- awesome.x ----------------------------
#if (BUILD_THERE == 1)
program THERE_PROG
{
version THERE_VER
{
void CALL_SERVER (int) = 1;
} = 1;
} = 0x31415926;
#endif
--- rpc_stuff.h --------------------------
#define YES 1
#define NO 0
void poll_for_RPC_requests (/*void*/);
CLIENT * setup_as_client ();
u_short register_as_server ();
CLIENT * setup_tcp_client ();
#ifdef MAIN_ROUTINE
char host[256];
#else
extern char host[256];
#endif
#define START_DIALOG "dia_go"
--- Makefile -----------------------------
CFLAGS = -g
all : rpc_stuff.o server client tags
tags :
ctags *.c *.h
rpc_stuff.o : rpc_stuff.c
awesome.h : awesome.x
rpcgen -h -o awesome.h -DBUILD_THERE=1 -DBUILD_BACK=1 awesome.x
there_clnt.c there_svc.c : awesome.x awesome.h
rpcgen -l -o there_clnt.c -DBUILD_THERE=1 awesome.x
rpcgen -c -o there_xdr.c -DBUILD_THERE=1 awesome.x
rpcgen -m -o there_svc.c -DBUILD_THERE=1 awesome.x
# this is the call back from 'server' back to 'client'
server : awesome.h there_svc.o server.o rpc_stuff.o
$(CC) $(CFLAGS) -o server server.o there_svc.o rpc_stuff.o
client : awesome.h there_clnt.o client.o rpc_stuff.o
$(CC) $(CFLAGS) -o client there_clnt.o client.o rpc_stuff.o
clean :
rm *.o
rm *_xdr.c
rm *_svc.c
rm *_clnt.c
rm server
rm client
------------------------------------------
When I don't define the macro TCP_CLIENT in 'client.c', my client and
server terminals look like the following (Note the "--call_server_1--"
on the server screen):
prompt> server
--main: server--
port addr = 129.172.208.239
drexler:register_as_server> Entering
port=1072 (0x0430)
--call_server_1(42)--
prompt> client drexler
ld.so: warning: /usr/lib/libc.so.1.6 has older revision than expected 7
kareem:main: client
kareem:setup_as_client> Link w/server (drexler)...GOOD link
main: client: calling call_server_1(42)
------------------------------------------
Then, when I define the macro TCP_CLIENT in 'client.c', my client and
server terminals look like the following (Note the ABSENSE of the
"--call_server_1--" on the server screen -- the server function never
gets called as far as its concerned):
prompt> server
--main: server--
port addr = 129.172.208.239
drexler:register_as_server> Entering
port=1070 (0x042e)
prompt>client 129.172.208.239.10.70
ld.so: warning: /usr/lib/libc.so.1.6 has older revision than expected 7
kareem:main: client
129 172 208 239 10 70
inet address: 0x81acd0ef
port=1070, 0x042e
kareem:setup_tcp_client> Server is drexler.nb.rockwell.com = 129.172.208.239
kareem:setup_tcp_client> TCP Link w/server...GOOD link
main: client: calling call_server_1(42)
------------------------------------------
Please help me Obi Wan -- you're my only hope. . .
Wade Guthrie
wade@nb.rockwell.com
Technical Details
Message-ID:
<1992Aug7.024026.29608@nb.rockwell.com>Path:
arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cs.utexas.edu!rice!nb.rockwell.com!wadeShow Full Headers
Complete Article Headers
Newsgroups: comp.unix.programmer Path: arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cs.utexas.edu!rice!nb.rockwell.com!wade From: wade@nb.rockwell.com (Wade Guthrie) Subject: RPC: clnttcp_create doesn't work Message-ID: <1992Aug7.024026.29608@nb.rockwell.com> Keywords: RPC clnttcp_create HELP Sender: wade@nb.rockwell.com (Wade Guthrie) Organization: Rockwell International Date: Fri, 7 Aug 1992 02:40:26 GMT Lines: 431