popen()
-
Dear community,
und zwar möchte ich ein Client, Server system programmieren das folgendes tun soll: Der Client soll mehrere Strings schicken können, die beim Server mittels popen(),als Kommandos interpretiert werden. Der Server soll dann,die Ausgabe vom Server wieder zurückschicken und der Client gibt den output in der Konsole aus.
Ich habe jetzt schon folgendes programmiert hier mal mein code:
server.c
include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include<fcntl.h> #include<unistd.h> #include <string.h> #include <stdlib.h> #define BUF 1024 int main() { int create_socket,new_socket; struct sockaddr_in address; socklen_t addrlen; char buffer[BUF]; int len; FILE *pipe; address.sin_family=AF_INET; address.sin_addr.s_addr=INADDR_ANY; address.sin_port=htons(6000); if((create_socket=socket(AF_INET,SOCK_STREAM,0))>0) printf("Socket erzeugt\n"); if((bind(create_socket,(struct sockaddr *) &address,sizeof(address))!=0)) printf("Der Port ist nicht frei\n"); listen(create_socket,5); addrlen=sizeof(struct sockaddr_in); new_socket=accept(create_socket,(struct sockaddr *)&address,&addrlen); if(new_socket > 0){printf("Ein Client (%s) ist verbunden...\n",inet_ntoa(address.sin_addr));} while ((len = read(new_socket, buffer, BUF-1)) > 0) { buffer[len]='\0'; if((pipe=popen(buffer,"r"))==NULL) printf("Fehler bei popen"); while (fgets(buffer, BUF, pipe) != NULL) { len=write(new_socket, buffer,strlen(buffer)); printf("%s",buffer); } pclose(pipe); } if(close(new_socket)==0) { printf("Socket geschlossen\n"); } return EXIT_SUCCESS; }
client.c
#include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include<fcntl.h> #include<unistd.h> #include <string.h> #include <stdlib.h> #define BUF 1024 int main() { int create_socket,new_socket; struct sockaddr_in address; socklen_t addrlen; char *buffer=malloc(BUF); int len; address.sin_family=AF_INET; address.sin_addr.s_addr=INADDR_ANY; address.sin_port=htons(6000); if((create_socket=socket(AF_INET,SOCK_STREAM,0))>0) printf("Socket erzeugt\n"); if((bind(create_socket,(struct sockaddr *) &address,sizeof(address))!=0)) printf("Der Port ist nicht frei\n"); listen(create_socket,5); addrlen=sizeof(struct sockaddr_in); new_socket=accept(create_socket,(struct sockaddr *)&address,&addrlen); if(new_socket > 0){printf("Ein Client (%s) ist verbunden...\n",inet_ntoa(address.sin_addr));} while ((len = read(new_socket, buffer, BUF-1)) > 0) { buffer[len]='\0'; write(new_socket, buffer,strlen(buffer)); } close(new_socket); return EXIT_SUCCESS; }
-
misti schrieb:
Dear community,
und zwar möchte ich ein Client, Server system programmieren das folgendes tun soll: Der Client soll mehrere Strings schicken können, die beim Server mittels popen(),als Kommandos interpretiert werden. Der Server soll dann,die Ausgabe vom Server wieder zurückschicken und der Client gibt den output in der Konsole aus.
Ich habe jetzt schon folgendes programmiert hier mal mein code:
server.c
include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include<fcntl.h> #include<unistd.h> #include <string.h> #include <stdlib.h> #define BUF 1024 int main() { int create_socket,new_socket; struct sockaddr_in address; socklen_t addrlen; char buffer[BUF]; int len; FILE *pipe; address.sin_family=AF_INET; address.sin_addr.s_addr=INADDR_ANY; address.sin_port=htons(6000); if((create_socket=socket(AF_INET,SOCK_STREAM,0))>0) printf("Socket erzeugt\n"); if((bind(create_socket,(struct sockaddr *) &address,sizeof(address))!=0)) printf("Der Port ist nicht frei\n"); listen(create_socket,5); addrlen=sizeof(struct sockaddr_in); new_socket=accept(create_socket,(struct sockaddr *)&address,&addrlen); if(new_socket > 0){printf("Ein Client (%s) ist verbunden...\n",inet_ntoa(address.sin_addr));} while ((len = read(new_socket, buffer, BUF-1)) > 0) { buffer[len]='\0'; if((pipe=popen(buffer,"r"))==NULL) printf("Fehler bei popen"); while (fgets(buffer, BUF, pipe) != NULL) { len=write(new_socket, buffer,strlen(buffer)); printf("%s",buffer); } pclose(pipe); } if(close(new_socket)==0) { printf("Socket geschlossen\n"); } return EXIT_SUCCESS; }
client.c
#include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include<fcntl.h> #include<unistd.h> #include <string.h> #include <stdlib.h> #define BUF 1024 int main() { int create_socket,new_socket; struct sockaddr_in address; socklen_t addrlen; char *buffer=malloc(BUF); int len; address.sin_family=AF_INET; address.sin_addr.s_addr=INADDR_ANY; address.sin_port=htons(6000); if((create_socket=socket(AF_INET,SOCK_STREAM,0))>0) printf("Socket erzeugt\n"); if((bind(create_socket,(struct sockaddr *) &address,sizeof(address))!=0)) printf("Der Port ist nicht frei\n"); listen(create_socket,5); addrlen=sizeof(struct sockaddr_in); new_socket=accept(create_socket,(struct sockaddr *)&address,&addrlen); if(new_socket > 0){printf("Ein Client (%s) ist verbunden...\n",inet_ntoa(address.sin_addr));} while ((len = read(new_socket, buffer, BUF-1)) > 0) { buffer[len]='\0'; write(new_socket, buffer,strlen(buffer)); } close(new_socket); return EXIT_SUCCESS; }
Sry für den doppelpost. Hab ausversehen auf den Absenden Button gedrückt.
Also der Server interpretiert die strings richtig, aber ich hab das problem mit dem output auf der Seite vom Clienten. Der zeigt mit nicht die gesamte Ausgabe an. Sprich manchmal schon manchmal nicht. Woran kann das liegen? Was mache ich falsch? Für Hilfe wäre ich sehr dankbar..mfg
misti
-
Wenn Du ein TCP-Socket benutzt, solltest Du beim Schreiben "in" diesen Socket immer den Rückgabewert von write() (besser Du nimmst send()) kontrollieren, da ein TCP-Paket abhängig von der Art des Netzwerkes (Ethernet, PPP über Modem, ...) unterschiedlich viele Zeichen umfassen kann (Stichwort MTU - maximum transfer unit). Wenn der Rückgabewert (=Anzahl der tatsächlich gesendeten Zeichen) kleiner als strlen(buffer) ist, musst du den Rest mit einem/mehreren weiteren send()-Aufruf hinterher schicken.
Wenn Du mit UDP (SOCK_DGRAM) arbeitest, kommt sogar ein Fehler, wenn die zu sendende Sequenz größer als ein IP-Paket (Netto) ist.
-
Sry mir ist gerade aufgefallen dass ich zwei verschiedene server.c geposte habe.
Hier nochmal die client.c
#include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include<fcntl.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <netdb.h> #include <string.h> #include<fcntl.h> #define BUF 1024 int main(int argv,char **argc) { int create_socket; struct hostent *host; struct sockaddr_in serv_adr; char buffer[BUF]; int len; if(argv!=2) printf("Usage:<server>\n"); if((host=gethostbyname(argc[1]))==NULL) perror("host"); if((create_socket=socket(AF_INET,SOCK_STREAM,0))>0) printf("Socket erzeugt\n"); memcpy(&serv_adr.sin_addr, host->h_addr, host->h_length); serv_adr.sin_port = htons(6000); serv_adr.sin_family=AF_INET; if (connect(create_socket, (struct sockaddr *) &serv_adr, sizeof(serv_adr)) < 0) { perror("connect error"); exit(1); } else { printf("Verbindung mit dem Server (%s) hergestellt\n",inet_ntoa(serv_adr.sin_addr)); } while(strcmp(buffer,"QUIT\n")!=0) { printf("Nachricht senden:\n"); fgets(buffer,BUF,stdin); write(create_socket,buffer,strlen(buffer)); if((len = read(create_socket, buffer, BUF-1)) > 0) { buffer[len]='\0'; //printf("Vom Server erhalten:\n"); printf("%s",buffer); } } if(close(create_socket)==0) printf("Socket geschlossen\n"); return 0; }
-
Hast Du den Wert von "BUF" mal testhalber herabgesetzt (siehe meine Antwort oben)? Tritt das Problem dann immer noch auf?
Gib doch einfach mal den Wert von "len" nach Zeile 49 in server.c (obere Version) aus.
-
Hi,
habe den wert jetz vom BUF heruntergesetzt und das len ausgeben lassen. Auf Server seite ist das len ok. Beim Clienten gibt er mir jetzt auch die Ausgabe scheibar okay aus. Aber er kommt nicht aus der while Schleife heraus damit ich den nächsten befehl schicken kann. Woran liegt das?
mfg
misti
-
misti schrieb:
[...] Aber er kommt nicht aus der while Schleife heraus damit ich den nächsten befehl schicken kann. Woran liegt das?
So wie ich das sehe, wartet der Client doch auf den String "QUIT\n". Dieser müsste jedoch vom Server kommen, da der letzte read()-Aufruf in der while()-Schleife (Zeile 52) den Buffer mit der Antwort vom Server überschreibt.
Dein Server erzeugt aber keinen solchen String!Ich vermute, dass Du das "QUIT\n" über die Tastatur eingeben wolltest. Dann müsstest Du aber nach dem fgets()-Aufruf in Zeile 50 den Buffer mit "QUIT\n" vergleichen.
-
while(1) { printf("Nachricht senden:\n"); fgets(buffer,BUF,stdin); if(strcmp(buffer,"QUIT\n")==0) exit(0); len=write(create_socket,buffer,strlen(buffer)); printf("len %d\n",len); if((len1 = read(create_socket, buffer, BUF-1)) > 0) { buffer[len1]='\0'; printf("%s",buffer); } }
Ich habs jetzt so umgeschrieben. Aber es geht nicht, Irgdnwas scneint das programm zu blockieren.
-
Vielleicht liegt's am read() oder write(). Versuch's doch mal mit den "richtigen" Funktionen send() und recv()!
Zum Testen solcher Client-Server-Programme ist es hilfreich, sich einen "Universal-Server" und "Universal-Client" zu schreiben, die einfach die empfangenen Zeichen ausgeben und die Tastatureingabe über den Socket schicken - also quasi Netzwerk-Chat-Tools. Für beides findest Du die Quelltexte in meinem Buch C und Linux.
PS.: Du solltest in Zeile 8 Deines letzten Posts exit(0) durch break; ersetzen. Dann wird die while()-Schleife und damit das Programm "sauber" beendet.