Spezialisten gefragt: Windows Socket: Empfangsschleife verschluckt Daten.
-
Hallo
Ein möglicher Schritt wäre z.B. mit Wireshark zu prüfen, ob tatsächlich korrekte daten gesendet und empfangen werden.
Dann, wenn das gegeben ist, würde ich das String Zeugs weglassen und nur auf Byte Ebene den Inhalt untersuchen. Stimmt alles?
So kannst Du Schritt für Schritt das Problem eingrenzen.
Simon
-
asc schrieb:
Mondmann schrieb:
...
Wäre noch schöner, da es nicht dein erster Post ist, wenn du das richtige Unterforum wählen würdest. Dann würde man dir vermutlich eher helfen. Windows Sockets sind mit Sicherheit kein ANSI C++.
cu André
Und welches wäre denn das richtige?
Könnte das ein Admin bitte verschieben?
Danke.
-
TCP? UDP? ...?
Und lies bitte nochmal aufmerksam die Doku zu send und recv. Wenn du mit TCP arbeitest machst du einiges falsch.
-
Übrigens bedeutet der return value 0 bei recv, dass der socket (gracefully) geschlossen wurde.
simon
-
simon.gysi schrieb:
Übrigens bedeutet der return value 0 bei recv, dass der socket (gracefully) geschlossen wurde.
simon
Ja das stimmt, aber ich bekomme niemals 0 zurück.
Er holt einfach 4095 Nullen (0) ab....
-
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.
-
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