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


  • Mod

    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 Wahnung

    client.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.


Anmelden zum Antworten