Socketprogrammierung Problem beim CLient



  • Hallo liebe User,

    ich beschäftige mich derzeitig mit der Socketprogrammierung unter UNIX. Ich habe eine Server/ Client Anwendung geschrieben. Der Benutzer soll dem Client ein Befehl mitteilen, dieser soll dann an den Server gesendet werden und dessen Ausgabe soll beim Client zu sehen sein.

    Das Funktioniert auch soweit, nur irgendwie bekomm ich durch eine Funktion '/0' rein. Wenn ich die bei der Ausgabe "rausfilter" (also ersetzte) durch Leerzeichen bekomme ich eine Ausgabe.

    Der 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];
    
    	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("Please enter the message: ");
    
    	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");
    	}
    
    	for(tmp=0; tmp<n; tmp++)
    	{
    		if(buffer[tmp] == '\0')
    			buffer[tmp] = ' ';
    	}
    
    	printf("%s\n",buffer);
    
    	close(sockfd); //Beenden der Verbindung
    	return 0;
    
    }
    

    Der 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>
    
    	void error(char *msg)
    	{
    		perror(msg);
    		exit(1);
    	}
    
    int main(int argc, char *argv[])
    { 
    	int x; 
    	char line[130]; 
    	FILE *fp; //ZUm schreiben in eine Datei
    	int sockfd, newsockfd, portno, clilen;
    	char buffer[256]; 
    	struct sockaddr_in serv_addr, cli_addr;
    	int n;
    
    	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");
    	}
    
    		while(1)
    		{
    
    				bzero(buffer,256);
    
    				n = read(newsockfd,buffer,255); //lese vom Client
    
    				if (n < 0)
    				{
    					 error("ERROR beim lesen vom CLient");
    				}
    
    				printf("Here is the message: %s\n",buffer);
    
    				fp = popen(buffer, "r");  //Erzeuge Datei zum Schreiben für System()
    
    					while ( fgets( line, sizeof strlen(line), fp))  //Schreibe alle Ausgaben in die Datei
    					{
    						n = write(newsockfd,line ,sizeof strlen(line));
    
    						if (n < 0) 
    						{
    							error("ERROR beim schreiben zum Client");
    						}
    					}
    			pclose(fp);
    
    			n = write(newsockfd,"I got your message\n",18);
    
    			if (n < 0)
    			{
    				 error("ERROR beim schreiben zum Client");
    			}
    
    		} 
    	close(sockfd);
    return 0; 
    }
    

    Ich nehm mal an das liegt an fgets oder strlen. GEnau weiß ich es nicht. Kann es vielleicht noch an etwas anderem liegen? Wäre es ggf. möcglich den String so zu manipluieren, dass die Leerzeichen weg wären?

    Freu mich über jede Antwort



  • Svolf schrieb:

    ich beschäftige mich derzeitig mit der Socketprogrammierung unter UNIX.

    Ich will ja nicht kleinlich sein, aber sicher, dass es kein Unix ist?

    Zu viel Code. Die \0 wird schon von den Strings kommen, aber ich versteh nicht ganz, wo dein Problem ist. Bevor zu Daten versendest, bzw. empfängst, weißt du doch, was du an der Hand hast und kannst den String entsprechend filtern oder manipulieren.



  • while ( fgets( line, sizeof strlen(line), fp))  //Schreibe alle Ausgaben in die Datei 
                         { 
                             n = write(newsockfd,line ,sizeof strlen(line));
    

    sizeof strlen(line) ist Blödsinn.
    sizeof Expression gibt die grösse des Typs von Expression zurück.
    Der Returntyp von strlen ist size_t , d.h. du könntest statt dessen auch gleich sizeof size_t schreiben.

    sizeof size_t ist üblicherweise 4 oder 8, und wenn du das einsetzt sollte dir auch klar werden was da schiefgeht.

    fgets schrieb:

    Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the End-of-File is reached, whichever comes first.

    Du übergibst also z.B. num=4, fgets speichert daraufhin max. (num-1) also 3 Zeichen + 1x '\0' als Terminator.
    Über den Socket schickst du dann wieder 4 Byte raus, also die (bis zu) 3 gelesenen Zeichen + 1x '\0'.

    Lösung:
    Ersetze das sizeof strlen(line) im fgets Aufruf durch sizeof(line) , und das sizeof strlen(line) im write Aufruf durch bloss strlen(line) .



  • Wieso ist dein UNIX code im WinApi forum?



  • Hey, dass hat super funktioniert. Danke .

    oh sorry, kam durch die suche in das Forum


Anmelden zum Antworten