Spezialisten gefragt: Windows Socket: Empfangsschleife verschluckt Daten.
-
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
-
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
-
Wenn Du wissen willst, wie viele Daten der Server geschickt hat, hast Du zwei Möglichkeiten:
1. Du wartest eine gewisse Zeit bis nix mehr kommt (sehr unzuverlässig)
2. Du änderst Dein Protokoll, damit Du erkennen kannst, ob noch Daten kommenDas 2. würde ich Dir empfehlen.
Wenn dabei schon vor dem Senden feststeht, wieviel gesendet werden soll, so schicke doch diese Länge zuerst (zB. immer 4 Bytes Prefix mit der Länge). Und dann die Daten.
-
Ok, Mondmann, was du anscheinend (denke ich zumindest) nicht verstanden hast:
Wieviel bytes recv auf einmal empfängt ist purer Zufall. Wenn du 4095 Bytes rausschickst kann es sein dass recv nur 100 Bytes empfängt oder nur eins. Wenn du die restlichen Bytes haben willst musst du recv solange wieder aufrufen bis alles angekommen ist was du haben wolltest.Wenn du also "Pakete" verschicken willst, und der Empfänger vorher nicht wissen kann wie gross ein Paket ist, dann wäre wohl die beste Lösung vorher mitzuschicken wie gross es ist.
Zum Empfangen holst du dir dann zuerst einen Block von z.B. 4 Bytes (wenn die die Länge als 4 Byte Integer verschickst), und dann nochmal N Bytes für die Daten.Also das was Jochen Kalmbach vor mir schon beschrieben hat (sehe ich erst jetzt).
-
Ja das stimmt, das hab ich nicht verstanden bisher.
Wir haben uns schon überlegt immer die Menge der Bytes vorauszuschicken, eine Art Header für den Gesamten Kommunikationsprozess.
Ich schätze mal etwas anderes bleibt nicht übrig.
Ich werde morgen nochmal genau prüfen was recv empfängt und wo die Daten geblieben sind.
Es fehlen nämlich auch manchmal ganze "Pakete".Ich denke das Problem liegt auch daran, daß die Software die Daten zu schnell rausballert, ehe ich alle empfangen kann.
Dann läuft der Socket voll und ist blockiert.
Kann sowas sein?
Ist nur ne Theorie...
Wir wissen nicht wirklich was da auf dem Socket passiert nur, daß es nicht wirklich funktioniert.Wir haben schon ne Sendeverzögerung eingebaut, da hats ein bischen besser funktioniert aber das ist eine Sisyphosarbeit.
Ich werde dann morgen berichten...
Mondmann
-
Wenn Du "TCP" verwendest, dann kommen die Daten zuverlässig an. D.h. es geht nix verloren!
-
Hm...es gingen aber schon definitiv Pakete verloren...