⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rpctalk.c

📁 this gives details of the network programming
💻 C
字号:
#define PORTMAP#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <rpc/rpc.h>#include <string.h>#include "rpctalk.h"	/* generated by the protocol compiler */void setup_client(char *serverhost, u_long prog, u_long progvers);void eprint(char *s){  printf("%s\n",s);  exit(1);}/* some global variables */SVCXPRT *serv_handle;	/* transport handle used by the server */CLIENT  *clnt_handle;	/* client handle used when calling an RPC proc */int serv_sd;		/* server socket - used by select() */int client_established;	/* flag used to prevent multiple clients *//* define the remote procedures *//* procedure #1 gets a program number and hostname */void *sendprog_1( progid *p){  if (client_established)      {	printf("Multiple talk partner rejected\n");      }  else      {	client_established=1;	setup_client(p->hostname,p->prognum,TALKVERS);	printf("Talking with %s at prog %d\n",p->hostname,p->prognum);      }	  return(NULL);}/* procedure #2 gets a message and prints it */void *sendmesg_2( message *s){      printf("Received: %s",*s);      return(NULL);}/* RPC dispatcher - called by 	svc_getreqset(&rdset) */void dispatch( struct svc_req *rqstp, SVCXPRT *transp){  progid pg;  char mesg[200];  char *mptr = mesg;  switch (rqstp->rq_proc) {    /* 0 is the null proc (RPC "ping") */  case 0:    (void)svc_sendreply(transp, xdr_void, (char *)NULL);    break;      case SENDPROG:    /* other talk program is sending us it's RPC address */    if (svc_getargs(transp,xdr_progid,(char *) &pg)==FALSE) 	{	  svcerr_decode(transp);	  return;	}    sendprog_1(&pg);    break;  case SENDMESG:    /* other talk program is sending us a message */    if (svc_getargs(transp,xdr_message,(char *)&mptr)==FALSE) 	{	  svcerr_decode(transp);	  return;	}    sendmesg_2(&mptr);    break;  default:    svcerr_noproc(transp);    break;  }}/* create a udp socket, a transport handle,    and register with the portmapper    register each rpc routine with    the dispatcher*/int setup_server(u_long prog, u_long progver){  int serv_sd;  int serv_port;  struct sockaddr_in serv_addr;  int serv_len;    if ((serv_sd=socket(PF_INET,SOCK_DGRAM,0))==0)      eprint("Error creating socket");    serv_addr.sin_family = AF_INET;  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);  serv_addr.sin_port = htons(0);  serv_len = sizeof( serv_addr );  if (bind(serv_sd, (struct sockaddr *) &serv_addr, serv_len)<0)      eprint("Error binding\n");  if ((serv_handle = svcudp_create(serv_sd))==NULL)      eprint("Error creating server handle");  /* find out what port we are using */  if (getsockname(serv_sd, (struct sockaddr *) &serv_addr, &serv_len)<0)      eprint("Error getsockname\n");  serv_port = serv_addr.sin_port;/* register with the portmapper and the dispatcher */  pmap_unset(prog,progver);	/* unset just in case */  if (svc_register( serv_handle, prog,progver, dispatch, IPPROTO_UDP)==FALSE)      eprint("Problem registring with portmapper\n");    return(serv_sd);  }/* create a client handle which will be used to make RPC calls to   the other talk program (used to send messages)*/void setup_client(char *serverhost, u_long prog, u_long progvers){  struct timeval tm = {	0,0};    if ((clnt_handle = clnt_create(serverhost, prog, progvers, "udp"))==NULL)      eprint("Problem creating client handle\n");  /* set up client_handle to timeout immediately !!! */  clnt_control( clnt_handle,CLSET_RETRY_TIMEOUT,&tm);  clnt_control( clnt_handle,CLSET_TIMEOUT,&tm);}/* make an RPC call to the other talk program's SENDPROG procedure   this identifies us with the other process - telling it our   hostname and RPC program number*/void sendprognum(char *host,u_long prognum){  int stat;  struct timeval tm = {	0,0 } ;	/* timeout immediately */  progid pd;    pd.hostname = host;  pd.prognum=prognum;  stat = clnt_call( clnt_handle,SENDPROG,		   xdr_progid, (char *) &pd,		  xdr_void, NULL, tm);  /* we expect a timeout error since we timeout right away */  /* RPC server is not sending us a response anyway */  if (stat!=RPC_TIMEDOUT)      eprint("Problem with sending my address\n");  }/* make an RPC call to the other talk program's SENDMESG procedure    this sends a message we got from the keyboard to the other talk   program*/void sendmessage(char *s){  int stat;  struct timeval tm = {	0,0 } ;    stat = clnt_call( clnt_handle,SENDMESG,		   xdr_message,(char *) &s,		  xdr_void, NULL, tm);  /* we expect a timeout error since we timeout right away */  /* RPC server is not sending us a response anyway */    if (stat!=RPC_TIMEDOUT)      eprint("Error calling SENDMESG");  }/* custom svc_run(). This replaces the standard svc_run() supplied as    part of the RPC library. We need to provide our own so that we can look   for input from the keyboard as well as RPC requests from the other   talk program.   svc_fdset is a global variable provided by the RPC library.   svc_fdset is already initialized with all socket descriptors    corresponding to ports we are using to service RPC requests*/void svc_run( ){  fd_set rdset;  char s[101];  int readlen;  while (strncasecmp(s,"quit",4)!=0)      {	rdset = svc_fdset;	/* get a copy of the RPC socket read set */	FD_SET(0,&rdset);	/* add stdin to the set */	select( 100, &rdset, NULL, NULL, NULL);	/* first check to see if there is anything from the keyboard */	if (FD_ISSET(0,&rdset))	    {	      /* handle stdin */	      if ((readlen=read(0,s,100))==0)		  {		    /* EOF - quit */		    strcpy(s,"quit");		    continue;		  }	      else		  {		    if (client_established) 			{			  s[readlen]=0;	/* terminate the string */			  /* send the string to the other program */			  sendmessage(s);			}		    		  }	    }	FD_CLR(0,&rdset);		/* get rid of stdin before 					   calling svc_getreqset */	svc_getreqset(&rdset);		/* calls the dispatcher for					   each pending request */      }}/* main routine    if there is a command line argument assume it is the name of   a host that is already running this program (acting as an RPC   server for program number TALK).   if there is no command line argument - we are starting first.   setup to be an RPC server for program number TALK*/main(int argc, char **argv){  u_long myprognum;  char s[100];  if (argc==1)      {	/* we are the initial server - set to be an RPC server	   program number TALK        */	serv_sd = setup_server(TALK,TALKVERS);	myprognum = TALK;	/*	printf("Established as primary server\n"); */      }	  else       {	/* we are the secondary talk program 	   generate a random RPC program number,	   become an RPC server using that number	   send the primary server our RPC address	 */	myprognum = 300000+rand()%1000;	serv_sd = setup_server(myprognum,TALKVERS);	setup_client(argv[1],TALK,TALKVERS);	if (gethostname(s,90)<0)	    eprint("Error determining my hostname");	    	sendprognum(s,myprognum);	client_established=1;	/* printf("Established as client\n"); */      }  svc_run();	/* look for RPC requests and for input from keyboard */  pmap_unset(myprognum,1);	/* unregister with the portmapper */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -