0

Web tcp クライアントを実装することで、Web と tcp がどのように機能するかについて詳しく学ぼうとしています。

現在、私の Web リクエスト関数は次のようになっています。

    public string SendWebRequest(SocketWebRequest request)
    {
        using (NetworkStream ns = tc.GetStream())
        {
                using (System.IO.StreamReader sr = new System.IO.StreamReader(ns))
                {
                    request.WriteTo(ns);
                    ns.Flush();

                    var statusLine = sr.ReadLine();
                    ProcessStatusLine(statusLine);

                    Headers = ReadHeaders(sr);

                    ProcessCookies(request.Host);

                    int contentLength = 0;
                    if (Headers.ContainsKey("Content-Length"))
                    {
                        foreach (var cl in Headers["Content-Length"])
                        {
                            int buf;
                            if (int.TryParse(cl,out buf))
                            {
                                contentLength = buf;
                                break;
                            }
                        }
                    }
                    if (contentLength==0)
                    {
                        return "";
                    }

                    byte[] content = new byte[contentLength];

                    if (IsGziped())
                    {
                        MemoryStream decompressed = new MemoryStream();

                        using (var zs = new GZipStream(ns, CompressionMode.Decompress))
                        {
                            while (true)
                            {
                                var buf = new byte[1024];
                                int read = zs.Read(buf, 0, buf.Length);
                                if (read == 0)
                                {
                                    break;
                                }
                                decompressed.Write(buf, 0, read);
                            }
                        }
                        content = decompressed.ToArray();
                    }
                    else
                    {
                        using (BinaryReader rdr = new BinaryReader(ns))
                        {
                            rdr.Read(content, 0, content.Length);
                        }
                    }

                    var encoding = GetEncoding();

                    return encoding.GetString(content.ToArray());
                }

        }

    }

リクエストは次のようになります。

GET http://www.youtube.com/ HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*
Accept-Language: en-US
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Host:www.youtube.com

応答ヘッダーは次のようになります。

HTTP/1.1 200 OK
Date: Sat, 25 Aug 2012 19:46:51 GMT
Server: Apache
X-Content-Type-Options: nosniff
Content-Encoding: gzip
Set-Cookie: use_hitbox=d5c5516c3379125f43aa0d495d100d6ddAEAAAAw; path=/; domain=.youtube.com
Set-Cookie: VISITOR_INFO1_LIVE=av7rkkf4Sfw; path=/; domain=.youtube.com; expires=Mon, 22-Apr-2013 19:46:51 GMT
Expires: Tue, 27 Apr 1971 19:44:06 EST
Cache-Control: no-cache
P3P: CP="This is not a P3P policy! See //support.google.com/accounts/bin/answer.py?answer=151657&hl=en-US for more info."
X-Frame-Options: SAMEORIGIN
Content-Length: 18977
Content-Type: text/html; charset=utf-8

この後、最初のものはint read = zs.Read(buf, 0, buf.Length);時々機能しますが、次の例外で失敗することがよくあります:

The magic number in GZip header is not correct. Make sure you are passing in a GZip stream. I've tried reading the data as string, and it looks encoded.

Youtubeはブラウザ経由で正常に動作します。データを文字列として読み取ると、エンコードされているように見えます。

なぜこれが発生するのですか?どうすれば修正できますか?

アップデート

これは、送信中に何らかのエラーが発生したようです。10 のうち 5 つのケースでは機能し、他の 5 つのケースでは明白な理由なしに失敗します

場合のコードは次のとおりですIsGziped()

 bool IsGziped()
    {
        foreach (var h in Headers["Content-Encoding"])
        {
            if (h.ToLowerInvariant().Contains("gzip"))
            {
                return true;
            }
        }
        return false;
    }
4

2 に答える 2

1

StreamReader必ずしも必要なバイト数だけを読み取るとは限りません。内部バッファリングにより、さらに読み取ることができます。これにより、圧縮されたバイトが から取得され、内部バッファNetworkStream nsに入れられます。StreamReader

バイトが取得された後、 はGZipStreamそれらを読み取ることができません。

おそらく、バイナリ レベルで動作するカスタム ヘッダー解析ソリューションを使用する必要があります。StreamReader最小限のバイト数だけを読み取るように制限する方法はありません。

StreamReader他のリーダーと併用することはできません。

于 2012-08-25T21:09:18.717 に答える