需要注意的有以下几点:
1、通过socket页面请求后的receive内容不能经过string后再进行解压缩处理 会造成错误的gzip幻数报错
推荐使用流处理
2、正确分析返回内容 分割header和页面代码部分
3、对页面代码部分进行解压缩
4、重组header与解压缩后的页面代码
解压缩使用net2.0的GZipStream类 很方便
代码如下:
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.IO.Compression;
- using System.IO;
- using ICSharpCode.SharpZipLib.GZip;
- namespace 贴吧江湖
- {
- public class clsGzip
- {
- public static string DecompressGzip(MemoryStream stm)
- {
- string strHTML = "";
- GZipStream gzip = new GZipStream(stm, CompressionMode.Decompress);//解压缩
- using (StreamReader reader = new StreamReader(gzip, Encoding.GetEncoding("gb2312")))//中文编码处理
- {
- strHTML = reader.ReadToEnd();
- }
- return strHTML;
- }
- }
- }
socket类中对此方法的调用
- int bytes = 0;
- string page = "";
- MemoryStream ms = new MemoryStream();
- do
- {
- bytes = s.Receive(bytesReceived, bytesReceived.Length, 0);
- //Encoding gb2312 = Encoding.GetEncoding("gb2312");//将读取的字节数转换为字符串
- //page = page + gb2312.GetString(bytesReceived, 0, bytes);
- ms.Write(bytesReceived, 0, bytes);
- //Console.WriteLine(bytes);
- }
- while (bytes > 0);
- s.Close();
- Console.WriteLine(ms.Length);
- ms.Seek(0, SeekOrigin.Begin);//将流的读写位置移动到开头
- Encoding gb2312 = Encoding.GetEncoding("gb2312");//准备获取HTTP header中页面内容的大小
- page = new StreamReader(ms, gb2312).ReadToEnd();//将流读入到字符串准备分割
- string[] sArray = page.Split(new string[] { "/r/n/r/n" }, StringSplitOptions.RemoveEmptyEntries);//分割web服务器返回代码 分为头域和页面代码
- page = page.Substring(page.IndexOf("Content-Length: ") + 16);//分割字符串获得页面内容大小
- page = page.Substring(0, page.IndexOf("/r/n"));
- //Console.WriteLine(page);//输出经过gzip压缩的页面内容的大小
- long begin = ms.Length - Convert.ToInt64(page);//流长度-页面内容大小就是我们需要的页面内容在流内的起始位置
- ms.Seek(begin, SeekOrigin.Begin);//移动到此位置
- page = clsGzip.DecompressGzip(ms);//将流传递给解压缩方法
- //Console.WriteLine(begin);
- page = sArray[0] + "/r/n/r/n" + page;//将header与解压缩后的页面内容重新组合
- //Console.WriteLine(page);
- return page;
发送页面请求的时候注意加上Accept-Encoding: gzip, deflate/r/n
终于解决了。。。还希望有朋友遇到相同的问题少走弯路