Anmelden

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme mit RPC Programmierung



Finalbrainxp
12-11-2004, 17:48
Hi Leute, bin ganz neu bei Linux und habe gerade meine erstes RPC-Programm fertig. (Suse9.1)

Es funktioniert wunderbar, auch über Rechnergrenzen hinweg. Nur habe ich da ein übles Problem.

meinen client rufe ich so auf:

./client ServerName


Wenn ich jetzt einen Server anspreche, welcher keinen RPC-Dienst zur Verfügung stellt,
dann bekomme ich einen Time-Out Fehler. Das ist auch gut so, aber ich muss so im Schnitt
70 Sekunden warten bis der Fehler kommt. Wie kann ich das Timeout heruntersetzen bzw. deaktivieren ? Habe schon in etlichen HP's geschaut, aber es scheint keine optimale Lösung dafür zu geben. Habe schon clnt_control() und clntudp_create(...,time) probiert, aber am Timeout verändert sich nichts!

Hier mein ClientCode:





#include <stdio.h>
#include <rpc/rpc.h>
#include "prime.h"

main(int argc, char **argv)
{
int i;
CLIENT *cl; /* Client Handle */
prime_result *result; /* Pointer to result Paket */
prime_request request; /* request Paket */

if (argc == 4)
{
cl = clnt_create(argv[1], (unsigned int)PRIMEPROG, (unsigned int)PRIMEVERS,"udp"); //Hier dauert es bis zu 70 Sekunden!!

if (cl == NULL) { clnt_pcreateerror(argv[1]); exit(2); };

request.min = atoi(argv[2]);
request.max = atoi(argv[3]);

result = find_primes_1(&request, cl); /* remote procedure aufrufen */

for(i=0; i< result->length; i++)
printf("%d ist Primzahl\n", result->array[i]);

xdr_free((xdrproc_t)xdr_prime_result, (char*)result); /* Freigeben des Result-Arrays */

clnt_destroy(cl);
}
else
printf("USAGE: client [SERVER] [MIN][MAX]\n");
}



Hatte auch schon folgende Alternative Probiert:


#include <stdio.h>
#include <rpc/rpc.h>
#include "prime.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>

main(int argc, char **argv)
{
int i;
register CLIENT *cl; /* Client Handle */
prime_result *result; /* Pointer to result Paket */
prime_request request; /* request Paket */



if (argc == 4)
{
struct hostent *hp;
struct timeval t1;
struct sockaddr_in s_addr;
int sock = RPC_ANYSOCK;
register CLIENT *cp;
unsigned long n;

t1.tv_sec = 1;
t1.tv_usec = 0;
hp = gethostbyname (argv[1]);
bcopy (hp->h_addr, (caddr_t)&s_addr.sin_addr, hp->h_length);
s_addr.sin_family = AF_INET;
s_addr.sin_port = 0;


cl = clntudp_create(&s_addr, PRIMEPROG, PRIMEVERS, t1, &sock);

if (cl == NULL)
{
printf("test\n");
clnt_pcreateerror(argv[1]);
exit(2);
};

request.min = atoi(argv[2]);
request.max = atoi(argv[3]);

result = find_primes_1(&request, cl); /* remote procedure aufrufen */

for(i=0; i< result->length; i++)
printf("%d ist Primzahl\n", result->array[i]);

xdr_free((xdrproc_t)xdr_prime_result, (char*)result); /* Freigeben des Result-Arrays */

clnt_destroy(cl);
}
else
printf("USAGE: client [SERVER] [MIN][MAX]\n");
}



Weiss da nicht mehr weiter....

will einfach nur, das wenn ich einen Server anspreche, welcher nicht vorhanden ist, oder
kein RPC-Dienst anbietet (Keinen Portmapper), dass es direkt abgebrochen wird und
eine entsprechende Fehlermeldung ausgegeben wird *heul

Weiss jemand von Euch da ne Lösung ?
:)


Vielen Dank im vorraus

Freundlicher Gruss

Finalbrain

PS: Und wieder ein neuer Microsoft-Hasser :D

RapidMax
13-11-2004, 14:11
Hmm, ich bin noch nicht so tief in die RPC-Programmierung eingestiegen. Gibt es keine Möglichkeiten einfluss auf den RPC-Socket zu nehmen?
Wenn es keine Funktion gibt, um Einfluss auf den Timeout zu bekommen, könntest du es mit einem Dirty-Hack versuchen: Ein Socket auf den Portmapper-Port aufbauen und gleich wieder schliessen (eine Art connect()-Portscanning).

Gruss, Andy

Finalbrainxp
13-11-2004, 14:39
Hi RapidMax, erstmal vielen Dank für deine Antwort.

An so einen Dirty Hack habe ich auch schonmal gedacht, nur
würde ich es gerne auf die "konventionelle Art" lösen.

Es geht ja folgendermaaßen:

Ich verbinde mich zuerst zum Portmapper, und dieser gibt mir den
Port zurück, an dem ich meinen RPC mache.

Hier aus den manpages:



CLIENT *
clntudp_create(addr, prognum, versnum, wait, sockp)
struct sockaddr_in *addr;
u_long prognum, versnum;
struct timeval wait;
int *sockp;

This routine creates an RPC client for the remote program prognum, version versnum; the client uses use UDP/IP as a transport. The remote program is located at Internet address addr. If addr->sin_port is zero, then it is set to actual port that the remote program is listening on (the remote portmap service is consulted for this information). The parameter sockp is a socket; if it is RPC_ANYSOCK, then this routine opens a new one and sets sockp. The UDP transport resends the call message in intervals of wait time until a response is received or until the call times out. The total time for the call to time out is specified by clnt_call().
Warning: since UDP-based RPC messages can only hold up to 8 Kbytes of encoded data, this transport cannot be used for procedures that take large arguments or return huge results.

Hier kann ich also die Retry-Time einstellen. Diese interessiert mich ja nicht, sondern ich will die total-Time-out-Time. Diese ist in clnt_call() spezifiziert,
aber das Prob ist ja, das clnt_call() ja erst nach clntudp_create aufgerufen wird. Es hängt also alles an der Funktion clntudp_create(). Ich habe auch schon deren Time-struct auf 0 gesetzt, aber es ändert leider nichts. Verflixt, das muss doch auch Ohne dirty hack gehen...hmmmm..suche dann noch mal weiter...trotzdem vielen Dank (Würde es ja mit dirty Hack machen, aber dies ist eine UNI-Aufgabe, wo Diese nicht gut ankommen ;-))