Spezialisten gefragt: Windows Socket: Empfangsschleife verschluckt Daten.



  • while( (rec = recv(s,ze_ret,MAX_REC_BUF,0)) != SOCKET_ERROR && (strcmp(ze_ret,STOPSEQUENZ)) !=0 )
                {           
    
                if(DEBUGLEVEL==DEBUG_PARANOIA)
                log.M_Logdat_str(ze_ret,1);       
    
                    if(strlen(ze_ret)>2)
    

    hast du schonmal versucht zu überprüfen was der genaue return deines recv iss ?

    jede Zeile ist ein Packet mit 4095 Bytes der Rest wird mit 0 aufgefüllt.

    wie groß ist dein MAX_REC_BUF größer als 4095 ??

    wenn ja kann auch mal gut und gerne 2 oder 3 mal hintereinander dein paket drinn stehen und wenn du dann strlen machst zählt er nur bis zur ersten '0' alle folgenden zeichen oder eventuell folgenden pakete ignoriert er dabei.

    grundsätzlich solltest du gerade bei sockets nicht mir derartig eingekürztem quelltext arbeiten, das gibt nur stress und verwirrung beim debuggen



  • Also wenn ich einen leeren buffer kriege ist recv==4095.
    MAX_REC_BUF ist natürlich 4095 groß.

    Mal noch ne Frage zu Wireshark:

    Wie kriege ich denn das Teil dazu auf den Port 3300 zu lauschen?
    Ich kommuniziere mit der Software auf dem Port 3300, also ist der Destination Port auf jeden Fall 3300.
    Nur mit Port 330 Zeichnet er gar gar nichts auf. Mit dem Filter:

    tcp.dstport == 3300

    Sehe ich nur nen leeren Bildschirm.
    Hat da jemand nen tip?

    Wenn ich tcp.dstport == 80 schreibe, funktioniert es, es kommt alles mit Port 80.

    Ich teste das hier lokal, also Server und Client sind auf demselben Rechner...



  • 1. Wireshark 'lauscht' an allen ports
    2. Hast Du eine TCP Verbindung? (Ich nehme es an, wenn du im Wireshark nach tcp.dstport filterst).
    Dann gibts einen Server, der auf einem bestimmten Port im listen mode ist (und auf eingehende verbindungen wartet (mit accept). Wenn jetzt ein Client connect aufruft, wir eine Verbindung aufgebaut, welche aber je ein neuen Port erhalten. Das bedeutet einfach, dass Du im Wireshark nicht nur den listen port untersuchen musst (weil der eben nur für den Verbindungsaufbau wichtig ist).

    3. So wie ich das verstanden habe, sendest Du jedes mal 4095 bytes. Wenns wenig informationen sind einfach mit 0 aufgefüllt. Das scheint mir sehr verschwenderisch und unpraktisch. Sende doch nur soviel wie nötig ist.

    4. recv liefert die anzahl empfangenen bytes zurück. Prüfe diese, wie schon im vorherigen post erwähnt. Dann erhältst Du z.B. zuerst 1500 bytes, dann 1500 bytes und dann den Rest.

    5.

    Ich teste das hier lokal, also Server und Client sind auf demselben Rechner...

    Versuchs auf mit verschiednen Rechnern (zur not geht auch VirtualPC oder ähnlich). Wenn es mir Recht ist geht das lokal nämlich nicht mit Wireshark.

    simon



  • 1. Ja weiß ich,aber man kann ja die Filter setzen und somit bestimmte Ports ausfiltern.

    2. Ist mir auch klar, aber warschenlich gehts lokal echt nicht, werds mal von nem anderen PC versuchen.

    3. Ja so ist es.

    Das wäre eigentlich keinProblem, aber während dem Abholen signalisiert mir der SOcket, daß es etwas zum abholen gibt und ich hole ab.
    Dann ist die länge zwar 4095 aber es stehen nur nullen drin.
    Beim nächsten durchlauf sind es dann wieder die richtigen Daten.
    Ich weiß jetzt nicht, ob die Software zu schnell sendet, oder ob ich zu schnell/langsam abhole, auf jeden Fall passt es nicht zusammen.
    Irgendwann ist dann der Socket voll oder ganz leer und es passt nicht mehr.
    Was genau da abgeht, was auf dem Socket läuft und warum ich so viel nullen abhole, habe ich noch nicht raus.
    Aber darin liegt das Problem mit dem wir beide nicht fetig werden und er Kollege Programmiert ca. 15 Jahre länger als ich.

    Aber wir haben auch schon versucht nur die Bytes zu schicken die belegt sind. Also nur die länge des zu senden Strings.

    In meinem Empfangsbuffer in recv halte ich weiterhin 4095 als max. bereit.
    Ergebnis war, daß alles auf einmal kam.
    Was also vorher 50 Packete mit 4095 Bytes(jeweils 100 belegt) waren nun 2 Packete mit Randvollen Daten.
    Somit ist also die ganze Kommunikation durcheinander und nichts passt mehr.
    Die Software hat alles auf den Socket geschickt und ich habe es mit meinem Buffer von 4095 alles auf einmal abgeholt.

    Wir haben es auch schon mit Handshake versucht. Also ich quittiere jedes PAcket das ankommt.
    Funktioniert aber auch nicht korrekt, da ich wieder meine nullen abhole, obwohl die Software garantiert erst was abschckt, wenn sie das ack von mir erhalten hat.

    Werde es jetzt mal mit Wireshark nochmals versuchen, vielleicht kriege ich da was raus.



  • Könnte es auch irgendwas mit TTL zu zun haben?
    Daß Telegramme einfach verloren gehen?

    Kann man irgendwie prüfen ob der Socket leer ist bevor ich das nächste Telegramm raussende?



  • Hallo

    Hast Du jetzt geprüft wieviele bytes ankommen (mit dem return wert von recv(...))?
    Du könntest die anzahl empfangenen bytes z.B. tracen.

    Wenn es auf dem gleichen Rechner nicht Funktioniert, hat es garantiert nichts mit TTL zu run.

    Simon



  • Ja ich prüfe den Rückabewert von recv....



  • Aber in den beiden Code Sequenzen die zu sehen sind nicht (bzw. nur obs gut ging oder nicht).



  • Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • @Mondmann

    Was verstehst du unter "Telegramm"? Verwendest du TCP, dann hast du einen Stream und keine "Telegramme". Verwendest du UDP, dann nennt man es normalerweise "datagram" und nicht "Telegramm".

    Ansonsten weiss ich nicht genau wovon du redest.

    Nochwas: die Verwendung von strcmp/strlen/... wie in den von dir geposteten Codeschnipseln zu sehen ist IMO falsch. Und wie glaube ich schon mehrfach erwähnt wurde: der Returnwert von send/recv gibt an wieviel Daten wirklich übertragen wurden. Den musst du auswerten.

    Also. Bevor du jetzt wieder schreibst "ja ich werte den aus" poste doch mal den entsprechenden Code wo man sieht dass (und wie) er ausgewertet wird. Am besten die ganzen Sende- und Empfangsschleifen.

    Und: bist du sicher dass der Fehler nicht auf der anderen Seite (das 2. Programm mit dem der Server kommuniziert) liegt?



  • Die andere Seite zeichnet auch auf was sie raussendet und da gibts keine leeren strings.
    Ja ich verwende TCP, also streams.

    //Empfangen
    			while( (rec = recv(s,ze_ret,MAX_REC_BUF,0)) != SOCKET_ERROR && (strcmp(ze_ret,STOPSEQUENZ)) !=0 && recv != 0)
    			{			
    
    				if(DEBUGLEVEL==DEBUG_PARANOIA)
    				log.M_Logdat_str(ze_ret,1);		
    
    				//if(strcmp(ze_ret,STOPSEQUENZ)==0)break;
    
    				if(strlen(ze_ret)>2)
    				{	
    					if(strcmp(ze_ret,APP_CLOSE)==0)
    					{	empfang.append(ze_ret);
    						empfang.append("\r");
    						log.M_Errdat_str(FKT_error("004412",_zeile),1);
    						return;
    					}				
    
    					InterlockedIncrement(&real_rec_zaehler);
    					empfang.append(ze_ret);
    					empfang.append("\r");
    				}
    
    				memset(ze_ret,0,MAX_REC_BUF);
    			}//while
    

    Hier die ganze empfangsschleife.

    Ich habe es mittlerweile mit asio implementiert. Ergebnis:
    Dasselbe!

    Zwischen den empfagsstreams empfange ich immer wieder leere Streams.
    Der Rückgabewert von recv ist dann 2643 ,1123 oder sonstwas, aber es sind nur nullen...von vorne bis hinten.

    Revc gibt niemals 0 zurück und somit signalisiert der Socket daß etwas ansteht...empfängt dann aber 2643 nullen...ich verstehs einfach nicht.



  • simon.gysi schrieb:

    Versuchs auf mit verschiednen Rechnern (zur not geht auch VirtualPC oder ähnlich). Wenn es mir Recht ist geht das lokal nämlich nicht mit Wireshark.

    simon

    Hab ich..geht leider auch nicht..



  • du benutzt ja immer noch strlen!



  • Ja. bewusst.
    Wenn recv 2643 zurückgibt, es aber alles nur nullen sind, dann muss ich wohl oder übel den buffer prüfen.
    Ist dieser strlen=0 oder zumindest kleiner 2, habe ich wieder so ein Fall wie beschrieben....



  • aua



  • Ja aua.
    Der Rückgabewert von recv ist 2643 und strlen vom buffer ist 0.
    Und nun?



  • tjo, dann hast du wohl 2643 Bytes bekommen, wovon das erste Byte 0 ist.



  • Nein eben nicht..hab mir jedes einzelne byte angeschaut...alles 000000



  • Ok.
    Freund.
    Es wurde dir mehrfach gesagt was du falsch machst, und du ignorierst es einfach. Was sollen wir dir jetzt noch sagen?

    Falls du nicht weisst was ich meine: recv() gibt zurück wieviel Bytes empfangen wurde, aber das hat nichts damit zu tun was auf der send Seite an send() übergeben wurde!
    Wenn du send(..., 10000) machst kann es auf der recv Seite passieren dass recv erstmal 1400 Byte oder so empfängt, und dann erst den Rest. Anders gesagt: recv gibt dir die Daten in Häppchen zurück so wie sie gerade daherkommen und nicht wie sie gesendet wurden.

    Wenn du das berücksichtigst ist der von dir gepostete Code einfach nur falsch. Daher kann man auch nicht erwarten dass er funktioniert.
    Behebe erstmal DAS Problem (auf beiden Seiten, Server UND Client!) und vergiss bis dahin die Sache mit den "lauter Nullen".



  • hustbaer schrieb:

    Ok.
    Freund.
    Es wurde dir mehrfach gesagt was du falsch machst, und du ignorierst es einfach. Was sollen wir dir jetzt noch sagen?

    Ok.
    Ich es nicht ignoriert, sondern einfach nicht verstanden.

    Ich soll also den Rückgabewert von recv auswerten.
    Doch verstehe ich nicht was mir das bringen soll. Was erfahre ich dadurch?
    Ich erfahre doch, wieviel bytes recv aus dem Stream gelesen hat.

    Beispiel:
    Also der Server sendet ein Stream der 4095 bytes groß ist.
    das nenne ich mal ein Packet.
    Aus meinem ersten Beispiel erkennt man, daß ich unterschiedliche Packete mit unterschiedlich vielen belegten Bytes bekomme.
    Nehmen wir mal an, im 1. Packet sind effektiv 300bytes drin, der Rest bis 4095 wird vom Server mit 0 aufgefüllt.
    Jetzt empfange ich das erste Packet mit recv.
    Die Frage ist nun: Empfange ich 4095 Bytes oder 300???
    Empfange ich 300, weiß ich ja nicht ob das alle Daten waren, da ich immer unterschiedlich lange Daten kriege.

    Aber ok das kann ich mal genau austesten.
    Im Falle ich bekomme von recv nu die 300 zurückgeliefert, bringt mit die Auswertung gar nichts, da ich im Vorfeld ja nicht weiß ob es 300 oder 3000 bytes in einem Packet sind, die mir der Server liefert.

    Würde ich immer 4095 empfangen könnte ich den Rückgabewert auswerten und mit dem nächsten Schleifendurchlauf addieren bis ich 4095 zusammen habe.
    Dann wüsste ich auch, daß ich ein Packet vom Server bekommen habe.

    Der Server hingegen weiß wieviel bytes er senden soll und überprüft dieses auch mit dem Rückgabewert von send().

    Ist es das was ich tun soll?
    Ich hoffe ich konnte erläutern wo mein Denk-Knoten festsitzt...

    Danke für Eure Hilfe und schönen Sonntag noch.

    Mondmann


Anmelden zum Antworten