recv() Empfangsproblem



  • Einrücken verbessert, und der Rest 🙄

    warum ist strcat so falsch? Sind doch alles Zeiger auf char mit den ich arbeite?!

    FD_ZERO(&fd);
    	FD_SET(sock,&fd);
    
        do{  
    
        	retselect=select(sock, &fd, NULL, NULL, &time);   // null dann timeout,
        	if(retselect <1)
    
        		printf("no answer until %d seconds\n",time.tv_sec);
    
        	else{
    
        		printf("retselec: %d\n",retselect);
        		size_recv = recv(sock, buffer, sizeof(buffer), 0);
        		if(size_recv > 0){
    
        			for(c=0;c<size_recv; c++){
        				data_recv[strlen(data_recv)]=data_recv[c+strlen(data_recv)]+buffer[c];
        				if(buffer[c]=='\n'){
    
        					printf("newline gefunden, raus aus der Schleife\n");
            				printf("Bytes received: %d\n", size_recv);
            				printf("Recv: %s\n", buffer);
            				return sock;
        				}
    
        			}
        		}
    
        		else if (size_recv == 0) 
    
            		printf("Connection closed\n"); 
    
        		else 
    
            		printf("recv failed: %d\n", WSAGetLastError()); 
    		}
    
    	}while(retselect > 0 );
        printf("data_recv: %s\n",data_recv);
    
    return sock;
    }
    


  • strcat war falsch, weil recv() keine Strings empfängt, und daher auch keinen Null-Terminator anhängt.

    Jetzt ist es noch falscher.

    Was habt ihr Noobs bloss alle immer mit den ganzen String-Funktionen?



  • warum hat dann mein Rückgabewert von recv() dann den Wert 6 bei 4 übertragenen Bytes?

    send() war "1234"

    buffer[0] 49
    buffer[1] 50
    buffer[2] 51
    buffer[3] 52
    buffer[4] 10
    buffer[5] 0
    buffer[6] -23
    ...

    "jetzt noch falscher" bringt mir irgendwie nicht viel 🙄



  • _Neuling schrieb:

    warum hat dann mein Rückgabewert von recv() dann den Wert 6 bei 4 übertragenen Bytes?

    send() war "1234"

    buffer[0] 49
    buffer[1] 50
    buffer[2] 51
    buffer[3] 52
    buffer[4] 10
    buffer[5] 0
    buffer[6] -23
    ...

    "jetzt noch falscher" bringt mir irgendwie nicht viel 🙄

    Das Problem ist, dass es auch sein kann, dass du zuerst 3 bytes und dann in einem zweiten Aufruf von recv(..) nochmals 3 bytes erhältst. TCP ist stream-orientiert, du bist selbst für die Meldungsgrezen zuständig.



  • Ich habe einen Breakpoint direkt nach recv gesetzt um mir die Werte anzuschauen, demnach wurde recv nur einmal aufgerufen.



  • Es kann, muss muss nicht...

    Es kann z.B. auch folgende Situation auftreten:

    Auf der Senderseite:
    send(..) 6 bytes (nennen wir sie b0 bis b5, zusammen Meldung 1, kurz m1)
    send(..) 4 bytes (nennen wir sie b6 bis b9, zusammen Meldung 2, kurz m2)

    Auf der Empfängerseite:
    recv(..) 3 bytes empfangen (b0 bis b2) m1 angefangen
    recv(..) 2 bytes empfangen (b3 bis b4)
    recv(..) 3 bytes empfangen (b5 bis b7) m1 komplett, m2 angefangen
    recv(..) 2 bytes empfangen (b8 bis b9) m2 komplett

    Aus diesem Grund musst Du deinen Code so schreiben, dass er immer funktioniert, auch wenn recv(..) nicht genau eine Meldung in einem Aufruf empfängt.

    Edit

    warum hat dann mein Rückgabewert von recv() dann den Wert 6 bei 4 übertragenen Bytes?

    Weil 1. nicht "1234" sondern "1234\r" übertragen wurde - inkl. terminierender Null. Es wurden also 6 bytes übertragen.



  • Das habe ich verstanden, falls nicht alles gesendet wurde beim ersten Mal schaut select() ob über dem socket noch was ankommt und macht dann noch einmal den recv()-Aufruf, das funktioniert soweit ich das testen kann. Nur scheint mein Abspeichern der Bufferwerte nicht korrekt, aber ich weiß nicht warum.

    hustbaer schrieb:

    strcat war falsch, weil recv() keine Strings empfängt, und daher auch keinen Null-Terminator anhängt.

    Ich denke recv() empfängt keine Nullzeichen?



  • recv(..) empfängt das was du sendest. Wenn du eine terminierende Null mitsendest, wird sie natürlich auf übertragen. Der Punkt ist aber, dass recv(..) nicht unbedingt in einem Aufruf all das empfängt, was du gesendet hast. Und deshalb ist die Benutzung von strcat(..), strlen(..) etc. blödsinn.



  • okok! also hat mein Server für diesen Fall dummerweise eine Null mitgesendet.

    Demnach eine Null an mein recv anhängen und dann mit strlen oder strcat zusammensetzen. Oder gibts da eine elegantere Variante?

    size_recv = recv(sock, buffer, sizeof(buffer), 0);
        		buffer[size_recv] = buffer[size_recv]+1;
        		if(size_recv > 0){
    
        			for(c=0;c<size_recv; c++){
    
        				data_recv[strlen(data_recv)]=data_recv[c+strlen(data_recv)]+buffer[c];
    


  • Wie sagte meine Volksschullehrerin immer so schön: OIS FOISCH!

    Streng mal dein Hirn an und nerv uns nicht mit deinem Mistcode.



  • Also da fehlt's jetzt an den grundlegensten Grundlagen.
    Zeiger & Arrays und so...

    Schreib mal deinen Sende-Teil so um, dass er alles absichtlich stückchenweise abschickt, mit sagen wir mal ner Sekunde Pause dazwischen. Und natürlich ohne Null-Terminator angehängt.

    Dann kommt es auch stückchenweise aus recv() wieder raus, und du kannst den Code mal testen.

    Und dann lies dich nochmal schlau bezüglich Arrays.
    Beispielsweise...

    buffer[size_recv] = buffer[size_recv]+1;
    

    Das inkrementiert ein Element von buffer , und zwar das mit Index size_recv . Also das erste Byte das nach dem letzten korrekt empfangenen kommt.
    Das ist sicher nicht was du willst. (Und schon gar nicht bevor du nicht geprüft hast ob size_recv nicht etwa negativ ist!)

    Die Lösung, ohne jetzt weiter auf deinen Code einzugehen:
    Variante 1:
    Schreib in einer eigenen Variable mit wie viel schon empfangen wurde, und kopiere den hinzugekommenen Block einfach mit memcpy() (NICHT strcat oder sonst eine String-Funktion) hinter die bereits gepufferten Daten dran.

    Variante 2:
    Merk dir wie viel Daten schon in buffer gepuffert sind, und übergib dann gleich einen Zeiger auf das erste freie Byte in buffer an recv() . (Die Grösse die du an recv() übergibst musst du dabei natürlich auch anpassen!)



  • Mit mem-Befehlen habe ich vorher noch nicht garbeitet, daher bin ich wohl auch nicht drauf gekommen die zu benutzen, trotzdem Danke für die Geduld 👍

    FD_ZERO(&fd);
    	FD_SET(sock,&fd);
    
        do{  
    
        	retselect=select(sock, &fd, NULL, NULL, &time);   // null dann timeout,
        	if(retselect <1)
    
        		printf("no answer until %d seconds\n",time.tv_sec);
    
        	else{
    
        		printf("retselec: %d\n",retselect);
        		size_recv = recv(sock, buffer+loop_recv, sizeof(buffer), 0);
    
        		if(size_recv > 0){
    
        			memcpy(data_recv,buffer, loop_recv+size_recv);
        			loop_recv+=size_recv;
    
        			for(c=0;c<size_recv; c++){
    
        				if(buffer[c]=='\n'){
    
    						data_recv[loop_recv]= '\0';
        					printf("newline gefunden, raus aus der Schleife\n");
            				printf("Bytes received: %d\n", size_recv);
            				printf("Recv: %s\n", buffer);
            				printf("data_recv: %s\n",data_recv);
            				return sock;
        				}
    
        			}
    
        		}
    
        		else if (size_recv == 0) 
    
            		printf("Connection closed\n"); 
    
        		else 
    
            		printf("recv failed: %d\n", WSAGetLastError()); 
    		}
    
    	}while(retselect > 0 );
    


  • Nein.
    Du hast jetzt beide Varianten zu etwas kombiniert was wieder nicht funktioniert.
    Irgendwie kommt mir vor du scheinst entweder überhaupt gar keinen Plan von Arrays und Zeigern zu haben, und/oder ein schweres Aufmerksamkeitsproblem.


Anmelden zum Antworten