Ich verwende Socket
Klasse für meine Web-Client. Ich kann HttpWebRequest
nicht verwenden, da Socks-Proxys nicht unterstützt werden. Also muss ich die Header analysieren und die Chunked-Codierung selbst handhaben. Die schwierigste Sache für mich ist, die Länge des Inhalts zu bestimmen, also muss ich es Byte für Byte lesen. Zuerst muss ich ReadByte()
verwenden, um die letzte Kopfzeile ("\ r \ n \ r \ n" -Kombination) zu finden, und dann prüfen, ob der Körper eine Übertragungscodierung hat oder nicht. Wenn es tut, muss ich Chunk Größe etc lesen:Wie bekomme ich HTTP-Nachrichten mit Socket
public void ParseHeaders(Stream stream)
{
while (true)
{
var lineBuffer = new List<byte>();
while (true)
{
int b = stream.ReadByte();
if (b == -1) return;
if (b == 10) break;
if (b != 13) lineBuffer.Add((byte)b);
}
string line = Encoding.ASCII.GetString(lineBuffer.ToArray());
if (line.Length == 0) break;
int pos = line.IndexOf(": ");
if (pos == -1) throw new VkException("Incorrect header format");
string key = line.Substring(0, pos);
string value = line.Substring(pos + 2);
Headers[key] = value;
}
}
Aber dieser Ansatz hat sehr schlechte Leistung. Können Sie eine bessere Lösung vorschlagen? Vielleicht einige Open-Source-Beispiele oder Bibliotheken, die HTTP-Anfrage über Sockets behandeln (nicht sehr groß und kompliziert, aber ich bin ein Noob). Am besten wäre es, einen Link zum Beispiel zu senden, der den Nachrichtentext liest und die Fälle korrekt behandelt, wenn: content chunked-encoding, gzip- oder deflate-encoded ist, Content-Length-Header fehlt (Nachricht endet, wenn die Verbindung geschlossen wird). So etwas wie der Quellcode der HttpWebRequest-Klasse.
Upd:
int bytesRead = 0;
byte[] buffer = new byte[0x8000];
do
{
try
{
bytesRead = this.socket.Receive(buffer);
if (bytesRead <= 0) break;
else
{
this.m_responseData.Write(buffer, 0, bytesRead);
if (this.m_inHeaders == null) this.GetHeaders();
}
}
catch (Exception exception)
{
throw new Exception("Read response failed", exception);
}
}
while ((this.m_inHeaders == null) || !this.isResponseBodyComplete());
Wo GetHeaders()
und isResponseBodyComplete()
Verwendung m_responseData
(MemoryStream
) mit bereits empfangenen Daten: Meine neue Funktion sieht wie folgt aus.
Wenn Sie gerade diese Frage bearbeiten, mit Sachen, die Sie lästig finden, werde ich einfachere Antworten auf meine ursprüngliche Antwort hinzufügen. –
Können Sie WinInet nicht verwenden? http://msdn.microsoft.com/en-us/library/aa383996(VS.85).aspx –
Zugehöriges, mögliches Duplikat: http://stackoverflow.com/questions/11862890/c-how-to-execute- a-http-request-using-sockets – vapcguy