hi Ich habe eine Frage bezüglich der HTTP / TCP Übertragung an sich... normalerweise geht soweit ich das verstanden hab HTTP mit TCP so: -> SYN <- SYN/ACK -> ACK -> GET bild.gif <- HTTP header + erste Daten -> ACK <- FIN + restliche Daten -> ACK -> FIN <- ACK nach jedem datenpaket kommt ein ACK der lwIP ( 1.4.0) macht hier aber soetwas: -> SYN <- SYN/ACK -> ACK -> GET bild.gif <- HTTP header <- rest HTTP header + erste daten -> ACK (hier werden die 2 pakete zusammen in der seq/ack nummer gezählt) <- FIN + restliche daten -> ACK -> FIN <- ACK ich dachte erst "sliding window" aber hier werden die pakete "nur" später geACKed hier werden aber mehrere Pakete zusammen geACKed mir gehts darum wie man dieses "feature" nennt desweiteren kann es sein das der client zwischen HTTP header und dem rest header auch mal ein ACK sendet .. auch wenn es in das window passt. hier kracht es dann irgendwie ... bzw hier kommt dann eine retransmission
Nach jedem Datenpaket ein ACK zu senden ist recht ineffizient, das läuft auf ein Ping-Pong-Protokoll heraus. Normal ist das für TCP nicht; TCP wurde erfunden um besser zu sein. Gut, wenn ich auf einem 8bitter unbedingt TCP implementieren müsste, um mit einem Browser zu reden, würde ich das auch auf ein Ping-Pong-Protokoll herunterhandeln. Ein eigenes ACK-Paket wird normalerweise nur gesendet, wenn die Datenübertragung offenbar nur in eine Richtung erfolgt, sonst steckt die ACK-Information einfach mit im TCP-Header der Gegenrichtung; der Platz dafür ist sowieso reserviert. Außerdem bezieht sich ACK genaugenommen nicht auf Pakete, sondern auf die transportierten Bytes; mehrere Pakete mit einem ACK zu bestätigen ist also normal. Theoretisch wäre es sogar zulässig, nur ein halbes Paket zu ACKen; der Absender kann dann das ganze Paket wiederholen oder nur die hintere Hälfte, oder die hintere Hälfte + folgende Daten. Das ACK für das GET steckt z.B. in demselben Paket wie der HTTP-Header, weil der Server sowieso Daten zum Client schicken muß, da kann er das ACK gleich mitschicken. Wenn der Server sich mit dem nächsten Paket dann zu viel Zeit läßt, schickt der Client schonmal ein ACK, damit der Server weiß, daß sein erstes Paket (das mit dem HTTP-Header) angekommen ist und er das nicht wiederholen muß. Wenn der Server seine Pakete schneller hintereinander schickt, gibt's eben nur ein gemeinsames ACK für beide. Einen besonderen Namen gibt es für diese Situation aber nicht. Die "Window size" spielt dabei auch noch eine Rolle. Die steht auch in jedem TCP-Paket drin, und gibt an, wieviel die Gegenseite noch über das letzte ACK hinaus senden darf, also praktisch wieviel Platz der Empfänger noch in seinem Puffer hat. Je nachdem, wie schnell der Empfänger die Daten verarbeitet hat, kann das sehr klein werden, und der Absender (in diesem Fall wohl der Server) muß dann für jedes Paket einzeln auf ein ACK warten.
ich habe den fehler eingrenzen können ... aktuell habe ich einen fehler im MSS und windowsize ich muss das mit dem sliding window nochmal genau durchlesen ein einzelnes ACK nach einer contiguous übertragung von mehreren segemnten ist erlaubt einzig das SACK sollte ich glabe ich für den kleinen stack weglassen da ich sonst nur schwer die möglichkeit habe einzelne segmente zwischenzupuffern und die ACKs durchzuzählen was ch aktuell nicht beachte ist der window wert des ACK vom client nach 6 dateien mit 4 contiguous segmenten geht dem der puffer aus das ACK sendet er weil nur noch 500 byte window frei waren ich hab aber fröhlich 1460 bytes reingepackt deswegen fiel mir das bei einzelnen dateien nicht auf werde das morgen so umbauen das ich die windowsize einbeziehe und an die applikation weiterreiche mit der maximal möglichen anzahl an byts die ich senden kann dann sollte das gehen ...
Normalerweise kann der Applikation des Senders die Windowsize des Empfängers egal sein, weil der TCP-Sendepuffer dazwischen vermittelt. Die Applikation gibt höchstens so viele Daten an TCP wie eben noch in den Sendepuffer passen, TCP sendet die Daten aus dem Puffer, soweit es Flußkontrolle (Windowsize des Empfängers) und congestion control erlauben, und wenn ein ACK kommt, wird entsprechend wieder Platz im Sendepuffer frei. Auf kleinen Prozessoren, wo kein Platz für den Sendepuffer ist, sieht das natürlich anders aus; da muß TCP für jedes Paket, das es senden will, die Applikation nach den entsprechenden Daten fragen.
Nosnibor schrieb: > . Normal ist das für TCP nicht; TCP > wurde erfunden um besser zu sein. Gut, wenn ich auf einem 8bitter > unbedingt TCP implementieren müsste, um mit einem Browser zu reden, > würde ich das auch auf ein Ping-Pong-Protokoll herunterhandeln. Und dabei auf die Schnau... fallen. Moderne Betriebssysteme machen das nicht mehr mit.
Nosnibor schrieb: > Auf kleinen Prozessoren, wo kein Platz für den Sendepuffer ist, sieht > das natürlich anders aus; da muß TCP für jedes Paket, das es senden > will, die Applikation nach den entsprechenden Daten fragen. ja genau das versuche ich zu umgehen bisher habe ich ja bei eingehenden ACKs die ack/seq nummer geprüft und kann so feststellen ob die gegenseite alles richtig empfangen hat das macht das system zwar einfach aber auch langsam .. ich habe deswegen eine segmentliste für jede übertragung wo ich mir die reihenfolge , acknummer , seqnummer und flags sowie segmentsize merke so kann ich theoretisch jedes segment durch die applikation wiederherstellen wenn es korrekt geacked wurde lösche ich es aus der liste wenn ich 2 segmente sende (contiguous ) dann erstelle ich nur 1 segment mit eben passender größe ich habe heute etwas experimentiert .. dabei habe ich zB festgestellt das manche browser bei windowsize 1000bytes schreiben .. aber in den options steht ein multiplikator .. den ich bisher vergessen hatte ich habe diverse wireshark caps wo 5-8 segemnte gesendet werden und dann erst ein ACK erfolgt warum er aber so viel zeit hat 5-8 pakete zu senden hab ich nch nicht kappiert bei mir sendet er nach 2 paketen ein ACK ich sende eine MSS von 1460 und Window von 2*1460 liegt evtl auch daran
Jim Meba schrieb: > Nosnibor schrieb: >> . Normal ist das für TCP nicht; TCP >> wurde erfunden um besser zu sein. Gut, wenn ich auf einem 8bitter >> unbedingt TCP implementieren müsste, um mit einem Browser zu reden, >> würde ich das auch auf ein Ping-Pong-Protokoll herunterhandeln. > > Und dabei auf die Schnau... fallen. Moderne Betriebssysteme machen das > nicht mehr mit. Wenn es nicht auf Durchsatz ankommt, sollte das immer gehen. Als Empfänger kann ich jederzeit über die windowsize regeln, wann der Sender senden darf, und als Sender kann ich einfach aufs ACK warten, bevor ich das nächste Paket sende. Das wird dann allerdings langsam, weil der Empfänger eine Weile (200ms war mal standard) zögert, bevor er ein "leeres" ACK schickt. ützgür schrieb: > dabei habe ich zB festgestellt das manche browser bei windowsize > 1000bytes schreiben .. > aber in den options steht ein multiplikator .. den ich bisher vergessen > hatte Das sollte einfach abzustellen gehen: beim three-way-handshake die entsprechende Option nicht senden, dann weiß die Gegenseite, daß du kein window scaling kannst und sendet die echte windowsize ohne Multiplikator. Der Nachteil (max. 64kb Window) dürfte auf einem kleinen embedded System kaum ins Gewicht fallen, weil nicht so viele Daten zu senden sind. > > ich habe diverse wireshark caps wo 5-8 segemnte gesendet werden und dann > erst ein ACK erfolgt > warum er aber so viel zeit hat 5-8 pakete zu senden hab ich nch nicht > kappiert > > bei mir sendet er nach 2 paketen ein ACK Der Empfänger wird natürlich in jedem Paket, das er selber sendet, die aktuelle Ack-Nummer mitschicken. Wenn er selber keine Daten zu senden hat, muß er dazu leere Pakete schicken. Eine feste Vorschrift, wann er das machen soll, gibt es nicht, soweit ich weiß. Es war mal üblich, das nach 200ms zu tun, aber es gibt bestimmt Gründe (z.B. bessere Unterstützung des slow-start-Algorithmus) für komplizierteres Verhalten. Da würde ich mir einfach keinen Kopf drum machen, wann der Empfänger seine ACKs schickt, solange er es überhaupt tut. Und wenn, dann muß man sich auch die Zeitstempel der Pakete genau ansehen. Und nicht vergessen, wo der Wireshark sitzt: manchmal begegnen sich Pakete auf der "Leitung" (incl. Netzwerkadapter und Ethernet-Treiber), und im Wireshark sieht immer der eigene Netzwerkstack besser und vernünftiger aus als die Gegenseite.
Bei Windows Vista, 7 und 8 ist der Timeout 200ms. Bei Windows XP konnte man ihn in der Registry konfigurieren. Bei Linux ist der Timeout viel kürzer. Windows Programme können die Option TCP_NODELAY Setzen, um den Timeout ganz abzuschalten. Dann wird jedes empfangene Paket sofort quittiert. Telnet mahct das z.B. sinnigerweise. Leider gibt es keine Möglichkeit, dass der Server dem Client mitteilt, er soll bitte jedes Paket sofort quittieren.
> Es war mal üblich, das nach 200ms zu tun
Ursprünglich war es vorgesehen, dass der Empfänger jedes Paket einzeln
möglichst rasch quittiert. Dann kam der Nagle Algorithmus (RFC 896 und
RFC 1122) hinzu. Das danach neue Verhalten ist nicht mehr 100%
kompatibel zum alten. Und deswegen gucken die Micro-Webserver (die nur
kleine Window-Sizes unterstützen) jetzt in die Röhre.
Ich fände es gut, wenn die Web-Browser an dieser Stelle lernen würden.
Spätestens nach ein paar Paketen müsste der Browser merken, dass der
Server offensichtlich IMMER ein ACK für jedes Paket (oder für jedes n-te
Paket) erwartet. Darauf kann er sich einstellen, indem er beim nächsten
Verbindungsaufbau die Option TCP_NODELAY setzt.
Bei Curl kann man das übrigens netterweise per Kommandozeilenparameter
steuern.
Vor einigen Jahren gab es mal einen Workaround der bei Windows Clients
half, leider klappt er nicht mehr. Damals war Windows noch so gestrickt,
dass es nur volle Pakete (size=MSS) verzögert beantwortete. Nach dem
Motto " da kommt sicher noch mehr". Aber halbvolle Pakete hatte Windows
immer sofort beantwortet. Es gab dazu mal eine Patch für µIP, aber wie
gesagt wurde der zurück gezogen.
hi vielen dank für die antworten ... ich bekomme einfach nicht mehr als 2 pakete raus ... ohne das ein ACK folgt demnach kann man das zwar so laufe lassen .. das ist aber enormer aufwand für die verwaltung ebenso schwerfällig wenn doch mal ein zwischenACK kommt den fall bekomm ich nur schwer weggefiltert das mit der datenlänge ist auch so ein ding was ich schonmal gelesen habe. aber das scheint wirklich nur experimentell gewesen zu sein. der µIP hatte mal einen patch das er ein 2tes ACK sendet zwar leer .. aber eben kurz nach dem datepaket um dem client zum anfragen zu zwingen aber neuere browser verhalten sich da auch anders ... ich versuche mal noch diverse dinge ... habe bisher auch immer versuch caps von verschiedenen verbindungen anzuschauen und zu verstehen aufgrund der zigtausend RFCs blickt da glaube keiner mehr 100%ig durch
ützgür schrieb: > ich bekomme einfach nicht mehr als 2 pakete raus ... > ohne das ein ACK folgt > > demnach kann man das zwar so laufe lassen .. > das ist aber enormer aufwand für die verwaltung > ebenso schwerfällig wenn doch mal ein zwischenACK kommt > den fall bekomm ich nur schwer weggefiltert Das verwirrt mich jetzt langsam. Wo ist das Problem für den Sender, wenn mehr ACKs zurückkommen als erwartet? Wenn du partout nicht damit klarkommst, im unerwarteten Moment auf ein ACK reagieren zu müssen, dann schiebe das doch einfach auf: Wenn ein ACK reinkommt, einfach die nötige Information irgendwo speichern, und später dann entsprechend reagieren. Viel Information ist das ja nicht: - ein Flag, daß mindestens ein ACK empfangen wurde - die "größte" geACKte Sequenznummer - das aktuelle Ende (Sequenznummer) vom receive window Wenn in der Zwischenzeit mehrere ACKs kommen, muß man die Information nur updaten, aber mehr wird es davon nicht. > aufgrund der zigtausend RFCs blickt da glaube keiner mehr 100%ig durch In der aktuellen rfc-index.txt steht zu jedem RFC die Gültigkeit. Alles was nicht aufm "standards track" ist, ist eh nur Unterhaltungsliteratur, und zu jedem Standard-RFC steht da, durch welche es ergänzt oder ersetzt wurde. Alles was ausdrücklich optional ist, braucht man nicht implementieren, ebenso alles, wo nicht MUST oder SHOULD (gemäß RFC2119, IIRC) dabeisteht. Und wenn man dabei keine Fehler macht, ist man immer noch standardkonform, also wo ist das Problem? :) Im Ernst: eine verständliche und vollständige TCP-Beschreibung habe ich auch noch nie gesehen. Viel pessimistische Kreativität ("was könnte noch alles schiefgehen?") ist nötig, wenn man sein eigenes TCP bauen will, sonst macht man damit im Betrieb viele "interessante" Erfahrungen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.