public string GetHtml(string url, Encoding postEncodType = null, Encoding htmlEncodType = null, string referer = null, bool isPost = false)
    {
        Uri uri = null;
        try
        {
            uri = new Uri(url);
        }
        catch
        {
            return null;
        }
        IPHostEntry ipList = Dns.GetHostEntry(uri.Host);    //这里是比较耗时的
        IPAddress ip = ipList.AddressList[0];
        IPEndPoint ipEnd = new IPEndPoint(ip, uri.Port);
        //使用tcp协议 stream类型 (IPV4)
        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        try
        {
            socket.Connect(ipEnd);  //这里是比较耗时的
        }
        catch
        {
            return null;
        }
//这里添加http发送头,如GET / HTTP/1.1
//Host: www.163.com
//...
        byte[] ms = this.GetSendBytes(url, postEncodType, referer, isPost);
        try
        {
            //发送
            socket.Send(ms);
            int size = 1024, recv = 0;
            byte[] data = new byte[size];
            StringBuilder retHtml = new StringBuilder();
            Encoding realHtmlEcnodType = htmlEncodType == null ? Encoding.Default : htmlEncodType;
            do
            {
                recv = socket.Receive(data, data.Length, SocketFlags.None);
                retHtml.Append(realHtmlEcnodType.GetString(data, 0, recv));
            } while (recv > 0 && socket.Available > 0);
            //关闭链接
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
            return retHtml.ToString();
        }
        catch
        {
            return null;
        }
    }上面代码是我写的C#运用SOCKET模拟HTTP协议的一个函数,
但调用该方法返回的字符串却不正确,我希望它能返回HTTP头,及相关的HTML代码
但这个函数只返回了HTTP头,访问某些站点(如www.163.com),还不包含Content-Length,如下:
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 29 Mar 2011 16:26:13 GMT
Content-Type: text/html; charset=GBK
Transfer-Encoding: chunked
Vary: Accept-Encoding
Expires: Tue, 29 Mar 2011 16:27:33 GMT
Cache-Control: max-age=80
Vary: User-Agent
Vary: Accept
Content-Encoding: gzip
Age: 65
X-Via: 1.1 lnsy251:80 (Cdn Cache Server V2.0), 1.1 jxq221:80 (Cdn Cache Server V2.0)
Connection: keep-alivea
?
我这样就无法得到HTML代码,请高手指点,要如何做才正确呢!
希望能分别得到HTTP头和HTML代码

解决方案 »

  1.   

    其实可以用封装好的 HttpListener给你段代码参考
      // 检查系统是否支持
                if (!HttpListener.IsSupported)
                {
                    throw new System.InvalidOperationException(
                        "使用 HttpListener 必须为 Windows XP SP2 或 Server 2003 以上系统!");
                }
                // 注意前缀必须以 / 正斜杠结尾
                string[] prefixes = new string[] { "http://localhost:49152/" };
                // 创建监听器.
                
                HttpListener listener = new HttpListener();
                // 增加监听的前缀.
                foreach (string s in prefixes)
                {
                    listener.Prefixes.Add(s);
                }
                // 开始监听
                listener.Start();
                Console.WriteLine("监听中...");
                while (true)
                {
                    // 注意: GetContext 方法将阻塞线程,直到请求到达
                    HttpListenerContext context = listener.GetContext();
                    // 取得请求对象
                    HttpListenerRequest request = context.Request;
                    Console.WriteLine("{0} {1} HTTP/1.1", request.HttpMethod, request.RawUrl);
                    Console.WriteLine("Accept: {0}", string.Join(",", request.AcceptTypes));
                    Console.WriteLine("Accept-Language: {0}",
                        string.Join(",", request.UserLanguages));
                    Console.WriteLine("User-Agent: {0}", request.UserAgent);
                    Console.WriteLine("Accept-Encoding: {0}", request.Headers["Accept-Encoding"]);
                    Console.WriteLine("Connection: {0}",
                        request.KeepAlive ? "Keep-Alive" : "close");
                    Console.WriteLine("Host: {0}", request.UserHostName);
                    Console.WriteLine("Pragma: {0}", request.Headers["Pragma"]);
                    // 取得回应对象
                    HttpListenerResponse response = context.Response;
                    // 构造回应内容
                    string responseString
                        = @"<html>
                    <head><title>From HttpListener Server</title></head>
                    <body><h1>Hello, world.</h1></body>
                </html>";
                    // 设置回应头部内容,长度,编码
                    response.ContentLength64
                        = System.Text.Encoding.UTF8.GetByteCount(responseString);
                    response.ContentType = "text/html; charset=UTF-8";
                    // 输出回应内容
                    System.IO.Stream output = response.OutputStream;
                    System.IO.StreamWriter writer = new System.IO.StreamWriter(output);
                    writer.Write(responseString);
                    // 必须关闭输出流
                    writer.Close();                if (Console.KeyAvailable)
                        break;
                }
                // 关闭服务器
                listener.Stop();
      

  2.   

    再给个纯 Socket的  public void Run()
            {
                // 取得本机的 loopback 网络地址,即 127.0.0.1
                IPAddress address = IPAddress.Loopback;
                // 创建可以访问的端点,49152 表示端口号
                IPEndPoint endPoint = new IPEndPoint(address, 49152);
                // 创建一个 socket,使用 IPv4 地址,传输控制协议 TCP,双向、可靠、基于连接的字节流
                Socket socket = new Socket(
                    AddressFamily.InterNetwork,
                    SocketType.Stream,
                    ProtocolType.Tcp);
                // 将 socket 绑定到一个端点上
                socket.Bind(endPoint);
                // 设置连接队列的长度
                socket.Listen(10);
                Console.WriteLine("开始监听, 端口号:{0}.", endPoint.Port);
                while (true)
                {
                    // 开始监听,这个方法会阻塞线程的执行,直到接受到一个客户端的连接请求
                    Socket client = socket.Accept();
                    // 输出客户端的地址
                    Console.WriteLine(client.RemoteEndPoint);
                    // 准备读取客户端请求的数据,读取的数据将保存在一个数组中
                    byte[] buffer = new byte[4096];
                    // 接受数据
                    int length = client.Receive(buffer, 4096, SocketFlags.None);
                    // 将请求的数据翻译为 UTF-8
                    System.Text.Encoding utf8 = System.Text.Encoding.UTF8;
                    string requestString = utf8.GetString(buffer, 0, length);
                    // 显示请求的内容
                    Console.WriteLine(requestString);
                    // 状态行
                    string statusLine = "HTTP/1.1 200 OK\r\n";
                    byte[] statusLineBytes = utf8.GetBytes(statusLine);
                    // 准备发送到客户端的网页
                    string responseBody 
                        = @"<html>
                                <head><title>From Socket Server</title></head>
                                <body><h1>Hello, world.</h1></body>
                            </html>";
                    byte[] responseBodyBytes = utf8.GetBytes(responseBody);
                    // 回应的头部
                    string responseHeader =
                        string.Format(
                            "Content-Type: text/html; charset=UTF-8\r\nContent-Length: {0}\r\n",
                            responseBody.Length
                            );
                    byte[] responseHeaderBytes = utf8.GetBytes(responseHeader);                // 向客户端发送状态信息
                    client.Send(statusLineBytes);
                    // 向客户端发送回应头
                    client.Send(responseHeaderBytes);
                    // 头部与内容的分隔行
                    client.Send(new byte[] { 13, 10 });
                    // 向客户端发送内容部分
                    client.Send(responseBodyBytes);                // 断开与客户端的连接
                    client.Close();
                    if (Console.KeyAvailable)
                        break;
                }
                // 关闭服务器
                socket.Close();
            }
      

  3.   

    我写的不是WEB服务器,我是想用纯SOCKET来获取HTML代码,及相关的HTTP头如何实现?
      

  4.   

    gzip 记得好像是内容被压缩了吧? 这个是设置是否以压缩的形式访问,你如果访问的时候带了这个属性,返回的就是压缩后的内容,解的有时候时乱码,所以我怀疑那个问号是不是这个原因,你试试。再有就是你请求的地址带不带身份验证的? 如果是普通的Get 应该没问题,如果带身份验证的话,失败后服务器可能返回极少的内容来仅仅触发JS或者Ajax,所以只能看到 a ? 这样的,你先把压缩标示属性去了试试,或者看看你发送的HTTP头和数据~
      

  5.   

    那如何使用SOCKET实现HTML代码的读取呢?
      

  6.   


    private static string GetPage(string url)
            {
                Uri URI = new Uri(url);
                string strHTML = "";//用来保存获得的HTML代码
                IPHostEntry gist = Dns.GetHostEntry(URI.Host);//获得当前URL的IP地址
                IPAddress ip = gist.AddressList[0];//提取IP地址
                IPEndPoint ipEnd = new IPEndPoint(ip, 80);//封装IP地址和端口
                Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//实例化Stock
                try { socket.Connect(ipEnd); }//自动循环捕捉连接
                catch { }
                string sendstr = string.Format("GET {1} HTTP/1.1\r\nConnection:close\r\nContent-Type: application/x-www-form-urlencoded\r\nHost:{0}\r\n\r\n", URI.Host, URI.PathAndQuery);//定义HTTP协议头部
                byte[] ms = UTF8Encoding.UTF8.GetBytes(sendstr);//将头部转换成byte形式
                socket.Send(ms);//发送
                int recv = -1;//定义接受数据长度
                byte[] data = new byte[1024];//用来保存接收数据
                do
                {
                    recv = socket.Receive(data);
                    strHTML += Encoding.Default.GetString(data, 0, recv);
                } while (recv != 0);
                return strHTML;
            }
      

  7.   

    asp.net封装了WebClient、HttpWebRequest,不需要直接用socket。
      

  8.   


    这个我了解,但我不想用它们,使用SOCKET如何模拟呢?还有9楼的代码不行!
      

  9.   

    “不想用”,那你也应该去看HttpWebRequest的源代码嘛。
      

  10.   

    这个问题不是那儿吧,应该是返回的头中是用 chunked的编码 的,你要先解码body 才能显示出来,还有我写这个程序的时候同步 没问题,用socket异步发送请求和 异步接收响应消息及内容时候  有点小问题,现在还没解决
      

  11.   

    对了  还有 body里面 也用了 gzip 压缩,来的内容也要解压 ,才能显示,这个一定要解码才能显示,我也是解码才能显示的