Aufgeteilte Codierung Implementation in .NET (oder zumindest pseudo code)
-
11-07-2019 - |
Frage
Ich schrieb ein Raw TCP-Client für HTTP / HTTPS-Anfragen, jedoch bin ich Probleme mit aufgeteilte Codierung Antworten habe. HTTP / 1.1 ist Voraussetzung deshalb sollte ich es unterstützen.
Raw TCP ist eine Business-Anforderung, die wir halten müssen, deshalb kann ich nicht wechseln zu .NET HttpWebRequest / HttpWebResponse Allerdings, wenn es Art und Weise eines RAW-HTTP-Request / Response in HttpWebRequest / zu konvertieren HttpWebResponse dass würde funktionieren.
Lösung
Der beste Ort, um die HTTP 1.1-Spezifikation , die legt Sie heraus, wie Chunking funktioniert. Im einzelnen Abschnitt 3.6.1.
3.6.1 segmentierte Übertragungscodierung
Die aufgeteilte Codierung ändert die Körper einer Nachricht, um
übertragen sie als eine Reihe von Stücken, jede mit ihrer eigenen Größenanzeige,
durch einen optionalen Anhänger gefolgt enthält entity-Header-Felder. Diese ermöglicht dynamisch erzeugten Inhalte zusammen mit dem
übertragen werden Informationen, die für die Empfänger zu überprüfen, ob es
die vollständige Nachricht empfangen hat.Chunked-Body = *chunk last-chunk trailer CRLF chunk = chunk-size [ chunk-extension ] CRLF chunk-data CRLF chunk-size = 1*HEX last-chunk = 1*("0") [ chunk-extension ] CRLF chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) chunk-ext-name = token chunk-ext-val = token | quoted-string chunk-data = chunk-size(OCTET) trailer = *(entity-header CRLF)
Die Brockengröße Feld ist eine Reihe von Hex-Ziffern, die die Größe der Häuser die Klumpen. Die aufgeteilte Codierung ist Ende von jedem Brocken, deren Größe
Null, gefolgt durch den Anhänger, der durch eine Leerzeile beendet wird.Der Anhänger ermöglicht es den Absender umfassen
zusätzliche HTTP-Header Felder am Ende der Nachricht. Das Trailer-Header-Feld kann verwendet werden, zeigen die Header-Felder sind Abschnitt in einem Anhänger enthalten (siehe 14.40).
Unter der Annahme, dass Sie bereits die Header aus der Antwort lesen und Ihr Pseudo-Code auf das nächste Byte weist in dem Strom in etwa so aussehen:
done = false;
uint8 bytes[];
while (!done)
{
chunksizeString = readuntilCRLF(); // read in the chunksize as a string
chunksizeString.strip(); // strip off the CRLF
chunksize = chunksizeString.convertHexString2Int(); // convert the hex string to an integer.
bytes.append(readXBytes(chunksize)); // read in the x bytes and append them to your buffer.
readCRLF(); // read the trailing CRLF and throw it away.
if (chunksize == 0)
done = true; //
}
// now read the trailer if any
// trailer is optional, so it may be just the empty string
trailer = readuntilCRLF()
trailer = trailer.strip()
if (trailer != "")
readCRLF(); // read out the last CRLF and we are done.
Dies ignoriert den Chunk-Erweiterungsabschnitt, aber da es begrenzt ist mit einem „;“ es sollte es aufzuschlüsseln einfach sein. Dies sollte ausreichen, um Sie, um loszulegen. Beachten Sie, dass die chunksize Zeichenfolge nicht haben eine führende "0x".
Andere Tipps
Für die Zukunft Referenz auch fand ich diese:
length := 0
read chunk-size, chunk-extension (if any) and CRLF
while (chunk-size > 0) {
read chunk-data and CRLF
append chunk-data to entity-body
length := length + chunk-size
read chunk-size and CRLF
}
read entity-header
while (entity-header not empty) {
append entity-header to existing header fields
read entity-header
}
Content-Length := length
Remove "chunked" from Transfer-Encoding