Socketprogrammierung Daten übertragen
-
Hallo lieber User,
ich wollte eine kleine Server/ Client Anwendung schreiben. Der Benutzer soll dabei dem Client ein PATH mitteilen, wo er die Datei von einem Server laden soll.
Client
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> void error(char *msg) { perror(msg); exit(0); } int main(int argc, char *argv[]) { int sockfd, portno, n; struct sockaddr_in serv_addr; struct hostent *server; //ConnectVerbindung int tmp; char buffer[256]; //Länge für den Befehel char ausgabe[256]; int rval; char buf[0x1000]; if(argc<3) { fprintf(stderr, "usage %s hostname port\n", argv[0]); exit(0); //Alles OK } portno = atoi(argv[2]); //casten der Portnummer sockfd = socket(AF_INET, SOCK_STREAM, 0); //Socket vom Betriebssystem anfordern SOCK_DGRAM für UDP // 0 STD Protokoll if(sockfd<0) { error("ERROR opening socket"); } server = gethostbyname(argv[1]); //Servername in eine IP-Adresse umwandeln if(server == NULL) { fprintf(stderr, "ERROR, no such host\n"); exit(0); } /* Erzeuge die Socketadresse des Servers. * Sie besteht aus Typ, IP-Adresse und Portnummer. */ bzero((char *) &serv_addr, sizeof(serv_addr)); //memset würde auch gehen serv_addr.sin_family = AF_INET; //IPv4 Verbindung bcopy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,server->h_length); //Server IP-Adresse serv_addr.sin_port = htons(portno); //Portnummer if(connect(sockfd,&serv_addr, sizeof(serv_addr)) <0) //Stelle Verbindung her { error("ERROR connecting"); } printf("Geben Sie den Datenpfad an: "); bzero(buffer,256); //leere speicher mit /'0' fgets(buffer,255,stdin); // liest einen String durch Benutzereingabe n = write(sockfd,buffer,strlen(buffer)); if(n<0) { error("ERROR writing to socket"); } bzero(buffer,256); n = read(sockfd,buffer,255); if(n<0) { error("ERROR reading from socket"); } printf("%s\n",buffer); FILE *file = fopen("file", "wb"); while((rval = recv(sockfd, buf, sizeof(buf), 0)) > 0) { fwrite(buf, 1, rval, file); } close(sockfd); //Beenden der Verbindung return 0; }
Server
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <errno.h> #include <time.h> #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> //19.06.2012 void error(char *msg) { perror(msg); exit(1); } int main(int argc, char *argv[]) { int x; char line[130]; int sockfd, newsockfd, portno, clilen; char buffer[256]; struct sockaddr_in serv_addr, cli_addr; int n; char buf[0x1000]; int rval; if (argc < 2) { fprintf(stderr,"Kein Port ausgewählt\n"); exit(1); } sockfd = socket(AF_INET, SOCK_STREAM, 0); //Socket vom Betriebssystem anfordern SOCK_DGRAM für UDP // 0 STD Protokoll if (sockfd < 0) { error("ERROR beim öffnen des Sockets"); } /* Erzeuge die Socketadresse des Servers. */ bzero((char *) &serv_addr, sizeof(serv_addr)); portno = atoi(argv[1]); //Port muss gecastet werden serv_addr.sin_family = AF_INET; // IPv4-Verbindung serv_addr.sin_addr.s_addr = INADDR_ANY; // INADDR_ANY: jede IP-Adresse annehmen serv_addr.sin_port = htons(portno); //Portnummer /* Erzeuge die Bindung an die Serveradresse * (genauer: an einen bestimmten Port). */ if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) { error("ERROR beim binden "); } /* Teile dem Socket mit, dass Verbindungswünsche * von Clients entgegengenommen werden. */ listen(sockfd,5); /* Bearbeite die Verbindungswünsche von Clients in einer Endlosschleife.*/ clilen = sizeof(cli_addr); newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,&clilen); //ACCEPT BLOCKIERT SOLANGE BIS cLIENT VERBINDUNG AUFNIMMT if (newsockfd < 0) { error("ERROR beim verbinden"); } n = read(newsockfd,buffer,255); //Pfad vom Client printf("%s\n",buffer); while(1) { FILE *file = fopen(buffer, "rb"); while (!feof(file)) { rval = fread(buf, 1, sizeof(buf), file); send(newsockfd, buf, rval, 0); } } close(sockfd); return 0; }
Mein Problem ist, dass mir der Sever immer eine Zugriffsverletzung anzeigt. Und wenn ich in der Funktion fopen ein Pfad direkt angebe z.B. /etc/hosts dann schreibt er mir in die Datei aber das gleich mehrmals nicht nur einmal.
Würde mich freuen, wenn mir da jemand helfen kann
Danke
-
Da sind noch jede Menge oberflächlicher, technischer Fehler drin, teilweise ziemlich ernsthafte. Kümmere dich zuerst mal darum:
client.c: In function ‘error’: client.c:12:3: warning: implicit declaration of function ‘exit’ [-Wimplicit-function-declaration] exit(0); ^ client.c:12:3: warning: incompatible implicit declaration of built-in function ‘exit’ [enabled by default] exit(0); ^ client.c: In function ‘main’: client.c:32:7: warning: incompatible implicit declaration of built-in function ‘exit’ [enabled by default] exit(0); //Alles OK ^ client.c:35:3: warning: implicit declaration of function ‘atoi’ [-Wimplicit-function-declaration] portno = atoi(argv[2]); //casten der Portnummer ^ client.c:49:7: warning: incompatible implicit declaration of built-in function ‘exit’ [enabled by default] exit(0); ^ client.c:54:3: warning: implicit declaration of function ‘bzero’ [-Wimplicit-function-declaration] bzero((char *) &serv_addr, sizeof(serv_addr)); //memset würde auch gehen ^ client.c:54:3: warning: incompatible implicit declaration of built-in function ‘bzero’ [enabled by default] bzero((char *) &serv_addr, sizeof(serv_addr)); //memset würde auch gehen ^ client.c:57:3: warning: implicit declaration of function ‘bcopy’ [-Wimplicit-function-declaration] bcopy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,server->h_length); //Server IP-Adresse ^ client.c:57:3: warning: incompatible implicit declaration of built-in function ‘bcopy’ [enabled by default] bcopy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,server->h_length); //Server IP-Adresse ^ client.c:61:3: warning: passing argument 2 of ‘connect’ from incompatible pointer type [enabled by default] if(connect(sockfd,&serv_addr, sizeof(serv_addr)) <0) //Stelle Verbindung her ^ In file included from client.c:3:0: /usr/include/sys/socket.h:129:12: note: expected ‘const struct sockaddr *’ but argument is of type ‘struct sockaddr_in *’ extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); ^ client.c:70:3: warning: implicit declaration of function ‘write’ [-Wimplicit-function-declaration] n = write(sockfd,buffer,strlen(buffer)); ^ client.c:70:3: warning: implicit declaration of function ‘strlen’ [-Wimplicit-function-declaration] n = write(sockfd,buffer,strlen(buffer)); ^ client.c:70:27: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default] n = write(sockfd,buffer,strlen(buffer)); ^ client.c:80:3: warning: implicit declaration of function ‘read’ [-Wimplicit-function-declaration] n = read(sockfd,buffer,255); ^ client.c:96:3: warning: implicit declaration of function ‘close’ [-Wimplicit-function-declaration] close(sockfd); //Beenden der Verbindung ^ client.c:23:8: warning: unused variable ‘ausgabe’ [-Wunused-variable] char ausgabe[256]; ^ client.c:20:7: warning: unused variable ‘tmp’ [-Wunused-variable] int tmp; ^
test.c: In function ‘main’: test.c:73:37: warning: pointer targets in passing argument 3 of ‘accept’ differ in signedness [-Wpointer-sign] newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,&clilen); //ACCEPT BLOCKIERT SOLANGE BIS cLIENT VERBINDUNG AUFNIMMT ^ In file included from test.c:10:0: /usr/include/sys/socket.h:214:12: note: expected ‘socklen_t * __restrict__’ but argument is of type ‘int *’ extern int accept (int __fd, __SOCKADDR_ARG __addr, ^ test.c:80:3: warning: implicit declaration of function ‘read’ [-Wimplicit-function-declaration] n = read(newsockfd,buffer,255); //Pfad vom Client ^ test.c:95:3: warning: implicit declaration of function ‘close’ [-Wimplicit-function-declaration] close(sockfd); ^ test.c:29:7: warning: variable ‘n’ set but not used [-Wunused-but-set-variable] int n; ^ test.c:25:8: warning: unused variable ‘line’ [-Wunused-variable] char line[130]; ^ test.c:24:7: warning: unused variable ‘x’ [-Wunused-variable] int x; ^
Viele dieser Fehler können eventuell doch richtig sein (dazu müsste man nun von Hand die Einzelfälle prüfen, da du verhinderst, dass der Compiler die Prüfung vornimmt), jedoch mindestens die falsche Pointersignedness wird zur Laufzeit fast garantiert abstürzen. Also genau das, was du beobachtest.
-
In dem übertragenen PfFad ist noch das '\n' (Die Entertaste von der Eingabe) enthalten.
Und das
while{1
} (Server Zeile 86) ist eine Endlosschleife, da es dort kein break gibt.
-
include alle header files
beachte den typ den read und write zurückgeben
client überträgt den pfad mit \n hinten dran
file wird nicht geschlossen
ungenutzte variablen
benutze memset statt bzero
benutze memmove/memcpy statt bcopy
achte darauf, dass das '\0' übertragen wird !!!!!
prüfe den rückgabewert von fopen, send, read
aktualisiere deine Kommentare
wenn du cli_addr, clilen bei accept sowiso ignorierst dann frag sie doch gar nich ab
benutzt C/C++ codetags
-
Hey,
danke erst einmal für die schnellen Antworten.
Also beim Client hab ich jetzt nur noch eine Wahnungclient.c:74: warning passing arguments 2 of 'connect' from incompatible pointer typ
/ust/include/sys/socket.h:129: note: expected 'const struct sockaddr *' but arguments is of type 'struct sockaddr_in *'Server Ausschnitt
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,&clilen); //ACCEPT BLOCKIERT SOLANGE BIS cLIENT VERBINDUNG AUFNIMMT if (newsockfd < 0) { error("ERROR beim verbinden"); } n = read(newsockfd,buffer,255); //Pfad vom Client printf("%s\n",buffer); //NULL Terminierung wegen der Eingabe vom CLient buffer[n] = '\0'; if (buffer[strlen(buffer)-1] == '\n') buffer[strlen(buffer)-1] = '\0'; if (buffer[strlen(buffer)-1] == '\r') buffer[strlen(buffer)-1] = '\0'; while(1) { FILE *file = fopen(buffer, "rb"); while (!feof(file)) { rval = fread(buf, 1, sizeof(buf), file); send(newsockfd, buf, rval, 0); } fclose(file); break; } close(sockfd);
Client Ausschnitt
FILE *file = fopen("file", "wb"); while((rval = recv(sockfd, buf, sizeof(buf), 0)) > 0) { fwrite(buf, 1, rval, file); } fclose(file); printf("%s\n",buffer); close(sockfd); //Beenden der Verbindung
Es zeigt mir auch keinen Speicherzugriffsfehler mehr an. Und die Ausgabe beim CLient ist soweit auch richtig. Nur er speichert in die erzeugte Datei nur ein "TS". Kann mir da vielleicht jemand helfen?
-
tipp: freunde dich mit deinem debugger an.