wirre zeichen :(

Dieses Thema im Forum "C/C++" wurde erstellt von tobsucht, 31.01.2009.

  1. #1 tobsucht, 31.01.2009
    tobsucht

    tobsucht Grünschnabel

    Dabei seit:
    31.01.2009
    Beiträge:
    3
    Zustimmungen:
    0
    hallo,
    ich arbeite zur zeit an einem simplen IRC-chatprogramm in C++, bestehend aus einem client und einem server. mein problem ist, dass ich nicht in der lage bin nachrichten vom server zu empfangen bzw. zu parsen, damit der header wegfällt und z.b. noch ein "You have joined the channel Fußball" kommt, wenn man /join Fußball am client eingibt. ?(

    ich habe als erste sprache java gelernt und muss jetzt in C++ für die uni was proggen, abgabe ist am montag :( :hilfe2:

    ich empfange nur wirre zeichen vom server und hab keine ahnung woran das liegt. mein auto-login, eine simple nachricht an den server funzt auch irgendwie nicht, deshalb ist der auskommentiert..

    ich poste hier mal eine kurzform des quellcodes von meinem client.
    beim senden habe ich leider auch noch das ein oder andere problem. ich denke mal die hauptursache liegt darin, dass ich keine ahnung von strings und chars und die umwandlung zwischen beiden habe. (stichwort nullterminator etc.).

    wäre nett falls sich hier der ein oder andere experte der sache annehmen könnte, denn ich denke das die meisten fehler in meinem code auf dem selben problem beruhen.

    danke im vorraus,
    tobsucht

    Code:
    #include "client.h"
    
    using namespace std;
    	    
    		
    client::client(string hostname, string port, string nickname)  {
    
    	this-> hostname = hostname;
    	this-> port = port;
    	this->nickname= nickname;
    	topic="";
    	
    	startClient(hostname, port);
    
    }
    
    
    
    int client::startClient(string hostname, string port)  {
    
    
    const char *host; 
    const char *service; 
    service = port.c_str();
    host = hostname.c_str(); 
    
    int error; 
    struct addrinfo hints; 
    struct addrinfo *addr0; 
    
    memset(&hints, 0, sizeof(hints)); 
    //hints.ai_family = PF_UNSPEC;
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_protocol = IPPROTO_TCP; 
    hints.ai_flags = 0; 
    
    
    printf("Looking up host.."); 
    
    	if ((error = getaddrinfo(host, service, &hints, &addr0)) < 0) { 
    		perror(gai_strerror(error)); 
    		return 1; 
    	} 
    
    printf("  OK \n");
    int sockno; 
    struct addrinfo *addr; 
    
    for (addr = addr0; addr; addr = addr->ai_next) { 
    	
    	printf("Creating socket (ai_family=%d, ai_socktype=%d, ai_protocol=%d)...\n", 
    	addr->ai_family, 
    	addr->ai_socktype, 
    	addr->ai_protocol
    	); 
    	
    	if ((sockno = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol)) < 0) { 
    		perror("socket"); 
    		continue; 
    	}
    	printf("  OK \n");
    	printf("Connecting to host..."); 
    	if ((connect(sockno, addr->ai_addr, addr->ai_addrlen)) < 0) { 
    		perror("connect"); 
    		close(sockno); 
    		continue; 
    	} 
    	break; 
    } 
    if (!addr) { 
    	printf("No connection found\n"); 
    	return 1;
    }
    printf("  OK \n");
     
    freeaddrinfo(addr0); 
    
    
    bool first_login = true;
     std::string input;
     std::string cmd;
     
    fd_set read_set0;
    
    FD_ZERO(&read_set0);
    FD_SET(STDIN_FILENO, &read_set0);
    FD_SET(sockno, &read_set0);
    
    	do { 
    		char buffer[1024];
    		int res;
    		ssize_t length; 
    		//int length;
    		fd_set read_set = read_set0; 
    		if ((res = select(sockno + 1, &read_set, NULL, NULL, NULL)) > 0) { 
    							
    			/*	
    				// für auto-login, geht noch nicht.
    				if (first_login==true)  {
    						string logincmd = "/LOGIN ";
    						cmd = getCommand(logincmd).c_str();
    						cout<<"getCommand liefert: "<<cmd<<endl;
    						strcpy(buffer, cmd.c_str());
    						first_login = false;
    				}
    				else { */
    		
    					if (FD_ISSET(STDIN_FILENO, &read_set)) { 
    					printf("Read STDIN...\n");
    
    						if ((length = read(STDIN_FILENO, buffer, sizeof(buffer))) < 0) {
    							perror("read"); 
    							continue;
    						}					
    					//input = buffer;
    					cmd = getCommand(buffer).c_str();
    					cout<<"cmd: "<<cmd<<endl;
    					strcpy( buffer, cmd.c_str());
    					cout<<"buffer: "<<buffer<<endl;
    					buffer[length]='\0';
    					//strcpy( buffer, input.c_str());
    				}
    	
    				printf("Write socket...\n");
    				buffer[length]='\0';
    				if ((length = write(sockno, buffer, length)) < 0) { 
    						perror("write");
    						continue;
    					}
    				//} 
    
    	
    		if (FD_ISSET(sockno, &read_set)) { 
    			printf("Read socket...\n"); 
    			
    			if ((length = read(sockno, buffer, sizeof(buffer))) < 0) { 
    				perror("read"); 
    				continue;
    			cout<<"length: "<<length<<endl;
    			} 
    			else if (length == 0) { 
    				printf("Server closed connection\n"); 
    				break;
    			} 
    			printf("Write STDOUT...\n");
    			if ((length = write(STDOUT_FILENO, buffer, length)) < 0) { 
    				perror("write");
    				continue;
    			}
    			
    		buffer[length]='\0';
    		std::string tmp = buffer;
    		cout<<handleServerMessage(tmp)<<endl;	
    		//cout<<"inc_buffer: "<<buffer<<endl;			
    		}
    		} 
    	else if (res < 0 && errno == EINTR) { 
    		continue;
    	} 
    	else { 
    		perror("select"); 
    		return 1;
    	}
    	}
    		while (1); 
    		close(sockno); 
    	return 0;
    }
    
    
    std::string client::getCommand(string message)  {
    	
    	int msg_length = message.find(' ', 0);
    	std::string command = message.substr(0, msg_length);
    	int channel_msg_length = message.find('/', 0);
    	std::string oldname;
    	std::string oldtopic;
    	std::string cmd_code;
    
       
    	
    	
    	if ((command == "/JOIN" || command == "/join") && message.size() > 6) {
            channel = message.substr(msg_length+1, MAXCHANNELNAME);
               	cout<<"You are in channel "<<channel<<'.'<<endl<<flush;
    			cmd_code ="10101";   
    			cmd_code+=channel;
    			return cmd_code;
    	}
        
    
    	else if (((command == "/LOGIN") || (command == "/login")) && message.size() > 6) {	
    			cmd_code ="10001";
    			cout<<nickname<<endl;
    			cmd_code+=nickname;
    			cout<<cmd_code<<endl;
    			return cmd_code;
    	}
    			else {		
    				cmd_code ="10011";
    				cmd_code+=topic;
    				cout<<cmd_code<<endl;
    				return cmd_code;
    			}
    	}
    	
        else if ((command == "/PRIVMSG" || command == "/privmsg")  && message.size() > 10)  {
    			string buf1, buf2;
    			buf1 = message.substr(msg_length+1, message.find(' ', msg_length+1)-msg_length-1);
    			buf2 = message.substr(message.find(' ', msg_length+1)+1, message.size()-message.find(' ', msg_length+1)-1);
    			cmd_code="11011";
    			cmd_code+=buf1; // muss noch mit server synchronisiert werden
    			cmd_code+=buf2;
    			return	cmd_code;
    		
    	}
    	
    	
        else if ((command == "/QUIT" || command == "/quit") && message.size() == 5) {
    			cmd_code+="10010";
    			return cmd_code;
        }
    	
    	else if((channel_msg_length==-1)) {
    			cmd_code="10111";
    			cmd_code+=message;
    			return cmd_code;
    	}
    
    
    
    }
    
    
    
    std::string client::handleServerMessage(string message)  {
    
    std::string header=message.substr(0, 5);
    int server_msg_length = message.length();
    std::string modified_msg;
    	
    	if (header == "10111")  {
    		modified_msg = message.substr(5, server_msg_length);
    		return modified_msg;
    	}
    	else if (header == "10101") {
    		std::string temp = ("You are in channel ");
    		temp += modified_msg;
    		temp += '.';
    		return temp;
    	}
    }
    
    
    
     
  2. Anzeige

    Schau dir mal diese Kategorie an. Dort findest du bestimmt etwas.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  3. #2 Gott_in_schwarz, 31.01.2009
    Gott_in_schwarz

    Gott_in_schwarz ar0

    Dabei seit:
    22.04.2007
    Beiträge:
    546
    Zustimmungen:
    0
    Ort:
    Niedersachsen
    Sowas macht wahrscheinlich nicht das, was du denkst.

    Strings sind (zumindest in C..) einfach arrays vom Typ char, die (meistens) mit einem null-char ('\0' oder int-Wert 0) terminiert werden. (Mit C++ String-Objekten kenn ich mich nicht aus..)
    Was du da vergleichst, sollten die Anfangsaddresse der beiden Strings (ie nulterminierten char-Arrays) sein.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main(void) {
        char *foo = "hello";
        if (foo == "hello") {
            printf("foo address:     %p\n\"hello\" address: %p\n\n", foo, "hello");
        }
        char bar[6];
        bar[0] = 'h';
        bar[1] = 'e';
        bar[2] = 'l';
        bar[3] = 'l';
        bar[4] = 'o';
        bar[5] = '\0';
        if (bar == "hello") {
            printf("This shall never execute\n");
        }
        else {
            printf("bar as string:     \"%s\"   address: %p\n", bar, bar);
            printf("\"hello\" as string: \"%s\"   address: %p\n", "hello", "hello");
        }
        return 0;
    }
     
  4. #3 tobsucht, 31.01.2009
    Zuletzt bearbeitet: 31.01.2009
    tobsucht

    tobsucht Grünschnabel

    Dabei seit:
    31.01.2009
    Beiträge:
    3
    Zustimmungen:
    0
    doch tut es, wenn ich die handleServerMessage-Methode auskommentiere und /login eingebe funktioniert es. an diesem vergleich sollte es nich liegen.
    .
    .
    .
    EDIT (autom. Beitragszusammenführung) :
    .

    brauche ich vielleicht einen char variabler länge damit ich die nachrichten alle terminieren kann bevor nachdem read() drübergelaufen is und bevor
    Code:
    write(sockno, buffer, sizeof(buffer))
    beginnt?

    wenn ja, wie würdest du das am sinnvollsten anstellen? bislang empfängt der server nur nachrichten, die so aussehen:

    10001to???

    wobei 10001 der header für login ist, anschliessend sollte da tobi stehen und stattdessen bekomme ich 3 solcher komischen fragezeichen ausgegeben, also nicht das fragezeichen-symbol sondern eher eins, als könne meine konsole nix mit den zeichen anfangen..
     
  5. #4 marcellus, 01.02.2009
    marcellus

    marcellus Kaiser

    Dabei seit:
    09.05.2007
    Beiträge:
    1.392
    Zustimmungen:
    0
    Ich muss zugeben, dass ich bis jetzt nur mit C erfahrung gemacht hab und da ist das bearbeiten von strings etwas anders. Bist du dir sicher, dass
    Code:
    			cmd_code ="10101";   
    
    das tut was es tun soll?

    Im übrigen wüsste ich gern von wo du den ursprünglichen source hast, normalerweise mischt man printf und cout nicht. Im übrigen sind die dafür vorgesehenen includes gar nicht drinnen.

    Ich hab ehrlichgesagt nicht viel ahnung was das ganze programm machen sollte, aber ohne mit dem debugger drüberfahren zu können ist alles, was ich sagen kann schlichtweg geraten. Und so viel hab ich vom ++ auch nicht abbekommen, das mir da was direkt ins Auge springen würde.
     
  6. #5 bytepool, 01.02.2009
    bytepool

    bytepool Code Monkey

    Dabei seit:
    12.07.2003
    Beiträge:
    791
    Zustimmungen:
    0
    Ort:
    /home/sweden/göteborg
    Hi,

    konkret mit dem Socket Problem kann ich auch nicht wirklich helfen, da ich Socket Programmierung unter C++ noch nie gemacht habe. Auch mit std::string habe ich noch nie gearbeitet.

    Beim ueberfliegen sind mir nur eine ganze Reihe von Unregelmaessigkeiten aufgefallen.
    Wie marcellus schon schrieb, vermischt du printf und cout die ganze Zeit, das wird im Allgemeinen als schlechter Stil empfunden. Ausserdem benutzt du den Namensraum std, schreibst den Namensraum aber bei Strings trotzdem immer explizit dazu. Auch da wuerde ich sagen, entscheide dich fuer eins von beiden, entweder du benutzt "using namespace std" oder nicht. Ich persoenlich habe es lieber explizit.

    Aber am schlimmsten ist die Formatierung von dem Code, vollkommen inkonsistent. Ich persoenlich weigere mich mir Code naeher anzugucken der nicht mal konsistent formatiert ist.

    Bei C++ Klassen kommt die moegliche Benutzung stark darauf an welche Operatoren ueberladen wurden. Laut dieser Referenz, http://www.cppreference.com/wiki/string/string_operators, wurde der Zuweisungsoperator(=) so ueberladen dass eine Zuweisung von char* zu std::string funktioniert (z.B. std::string str = "foo"). Denn wenn ich mich richtig erinnere, wird in C und C++ eine Zeichenkette die mit "" definiert wurde, durch den Pointer auf das erste Element der Zeichenkette ersetzt, und gleichzeitig korrekt mit dem Nullterminator abgeschlossen. D.h.
    Code:
    char * szFoo = "foo"
    
    reserviert 4 Byte im Speicher fuer die Zeichenkette 'foo\0', und liefert den Zeiger auf 'f' zurueck.

    Was allerdings nicht in der Referenz steht, ist der Fall den Gott_in_schwarz angesprochen hat. Der Gleichheitsoperator(==) wurde scheinbar nur fuer zwei string Klassen ueberladen, aber nicht fuer string Klassen und char Pointer. Und "foo" liefert wie weiter oben beschrieben einen char Pointer auf 'f' zurueck. Ergo muesste es wahrscheinlich eher
    Code:
    if (header.compare("10111") == 0)
    
    heissen. Wie gesagt, selber nie getestet, aber das entnehme ich der Referenz.

    @marcellus
    Er schrieb dass es nur ein Auszug ist, das duerfte der Grund dafuer sein, dass die entsprechenden includes nicht da sind.

    mfg,
    bytepool
     
  7. Anzeige

    Vielleicht findest du HIER Antworten.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  8. karru

    karru OSX'ler

    Dabei seit:
    02.05.2006
    Beiträge:
    338
    Zustimmungen:
    0
    Wenn du sowas postest mach dir doch bitte wenigstens die mühe das etwas leslicher zu formatieren.
    Da bekommt man doch kopfschmerzen von und es ist mit Vim in 5 Tastenschlägen erledigt:
    In vim: gg=G<enter>

    http://rafb.net/p/alBVif16.html


    1. Also erstmal "10111" ist ja wohl ganz großes Pfui.
    Da weiß keiner was das sein soll, anscheinend nicht mal du!

    Und es wird auch NICHT das tun, was es soll, Punkt. Siehe 3a.

    2. Interessant wäre was für "wirre zeichen" du den überhaupt bekommst...

    3a. Hast du dir überhaupt schon das Protokoll IRC angeschaut?
    Hier die beste Anleitung die es gibt: http://www.faqs.org/rfcs/rfc1459.html ;)

    3b. Hast du dir angeschaut wie strings bzw. zeichenketten in C++ implementiert werden und gehandhabt werden? std::string, char* char** usw.?
    http://www.cplusplus.com/doc/tutorial/ntcs.html

    C/++ ist zu recht kein Java, auch wenn die Syntax die gleiche ist, muss man etwas mehr "tieferes" Wissen mitbringen, also informier dich ;)
     
  9. #7 tobsucht, 01.02.2009
    Zuletzt bearbeitet: 01.02.2009
    tobsucht

    tobsucht Grünschnabel

    Dabei seit:
    31.01.2009
    Beiträge:
    3
    Zustimmungen:
    0
    Hey,
    erstmal Danke für eure Antworten. Ich werde das Ganze mit printf und cout heute abend korrigieren, genauso die auch Formatierung. Ich habe den Code zum Teil aus einem Beispiel übernommen und dieses nutzte printf, während ich selbst cout präferiere. Desweiteren war die Formatierung dieses Beispiels suboptimal und ich selbst habe bei Textedit für Ubuntu leider keine Autoformat bzw Beautify-Funktion gefunden. Vielleicht habt ihr ja den ein oder anderen Tip für mich womit so etwas am besten geht. Für emacs habe ich leider kein passendes Macro und mich auch noch nicht damit beschäftigen können eins selbst zu schreiben. Die von marcellus vorgeschlagene Methode zum Vergleichen von char* und string baue ich gleich mal ein und schreibe dann hier rein ob ich Erfolg hatte oder nicht...

    Schönen Sonntag noch.
    MfG
    Tobsucht

    edit:karru hat zeitgleich mit mir gepostet, ich nehme mir das mit VIM mal zu herzen. ich brauche keine anleitung für IRC, da wir ein eigenes protokoll mit eigenem header gebastelt haben. 10001 bedeutet dass sich ein user am server anmeldet. die darauf folgenden zeichen sollen dann der nickname sein. ich hatte gehofft, dass ich meine probleme mit gefährlichen halbwissen und ein paar tips aus dem forum hier in den griff bekomme, da mir die zeit davon läuft. das ganze ist eine aufgabe für ein praktikum, welches is morgen abgeben muss, also ist heute nachtschicht angesagt. die komischen zeichen die ich meine sind in der ubuntu-konsole fragezeichen mit schwarzem hintergrund. also nicht die standard-fragezeichen "?" sondern eher so etwas wie ein symbol für unbekannte zeichen.
     
Thema:

wirre zeichen :(

Die Seite wird geladen...

wirre zeichen :( - Ähnliche Themen

  1. verwirrendes rechteproblem

    verwirrendes rechteproblem: Hallo Leute Heut hat mich etwas schwer verwirrt und ich hoffe Jemand von euch kann das aufklären. Folgende Situation: Wir müssen mit einem alten...
  2. Verwirrendes Problem!

    Verwirrendes Problem!: Hallo, ich habe folgendes Problem mit meinem Fileserver (SuSE Linux 9.0 / Samba 2.2.8a): Wenn ich mich mit dem Explorer (Win 2000 Client) auf...
  3. Suche in Datei doppelte Wörter in jeder Zeile bis zum dritten Leerzeichen...

    Suche in Datei doppelte Wörter in jeder Zeile bis zum dritten Leerzeichen...: Ich habe eine Textdatei in der ich Einträge bis zum 3. Leerzeichen mit den restlichen Zeilen (auch nur bis 3. Leerzeichen) vergleichen muss und...
  4. Wie kann ich x Zeichen hinter einem bestimmten Wort ausgeben ?

    Wie kann ich x Zeichen hinter einem bestimmten Wort ausgeben ?: In mehreren Dateien ist immer mehrfach ein bestimmtes Wort enthalten, gefolgt von einem "=". Ich möchte mir die dahinter folgenden 10 Zeichen...
  5. Zeichen an Zeilenanfang für bestimmten Zeilenbereich einfügen

    Zeichen an Zeilenanfang für bestimmten Zeilenbereich einfügen: Hallo, ich würde gerne in einem Textdokument, z.B. von Zeile 10 - 18, an den Zeilenanfang ein # einfügen. Habe mir schon diverse Seiten zu SED...