zoukankan      html  css  js  c++  java
  • Sokcet方式请求HTTP/HTTPS的封装类HttpHelper

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Net;
    using System.Net.Security;
    using System.Net.Sockets;
    using System.Security.Authentication;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Threading;
    using System.Threading.Tasks;
    /************************************************************************/
    /* Author:huliang
     * Email:huliang@yahoo.cn
     * 注意:转载请注明出处
     * 摘自:http://www.cnblogs.com/cxwx/archive/2013/01/18/2865948.html
    /************************************************************************/
    
    namespace LiangHu
    {
        /// <summary>
        /// HTTP协议头包装
        /// </summary>
        public class HttpHeader
        {
            public HttpHeader()
                : this("")
            {
            }
    
            public HttpHeader(string url)
            {
                this.Url = url;
            }
    
            public string Url
            {
                get;
                set;
            }
    
            public string Host
            {
                get;
                set;
            }
    
            public string Accept
            {
                get;
                set;
            }
    
            public string Referer
            {
                get;
                set;
            }
    
            public string Cookies
            {
                get;
                set;
            }
    
            public string Body
            {
                get;
                set;
            }
    
            Dictionary<string, string> m_Others = new Dictionary<string, string>();
    
            public string this[string key]
            {
                get
                {
                    return m_Others.ContainsKey(key) ? m_Others.ContainsKey(key) : null;
                }
                set
                {
                    Add(key, value);
                }
            }
    
            public void Add(string key, string value)
            {
                switch (key.ToUpper())
                {
                    case "URL":
                        this.Url = value;
                        break;
                    case "HOST":
                        this.Host = value;
                        break;
                    case "ACCEPT":
                        this.Accept = value;
                        break;
                    case "REFERER":
                        this.Referer = value;
                        break;
                    case "BODY":
                        this.Body = value;
                        break;
                    default:
                        if (!m_Others.ContainsKey(key))
                        {
                            m_Others.Add(key, value);
                        }
                        else
                        {
                            m_Others[key] = value;
                        }
                        break;
                }
            }
        }
    
        /// <summary>
        /// HTTP回应包装
        /// </summary>
        public class HttpResponse
        {
            internal HttpResponse(string header,
                byte[] body)
            {
                this.Header = header;
                this.Body = body;
            }
            
            //暂未将回应HTTP协议头转换为HttpHeader类型
            public string Header
            {
                get;
                private set;
            }
    
            public byte[] Body
            {
                get;
                private set;
            }
        }
    
        /// <summary>
        /// HttpHelper
        /// </summary>
        public static class HttpHelper
        {
            /// <summary>
            /// 提交方法
            /// </summary>
            enum HttpMethod
            {
                GET,
                POST
            }
    
            #region HttpWebRequest & HttpWebResponse
    
            /// <summary>
            /// Get方法
            /// </summary>
            /// <param name="url">请求地址</param>
            /// <param name="cookieContainer">Cookies存储器</param>
            /// <param name="encoding">返回内容的编码格式</param>
            /// <param name="others">其他需要补充的HTTP协议头</param>
            /// <returns>请求结果</returns>
            public static string Get(string url,
                CookieContainer cookieContainer,
                Encoding encoding,
                Dictionary<string, string> others = null)
            {
                return InternalHttp(HttpMethod.GET, url, null, cookieContainer, encoding, others);
            }
    
    
            /// <summary>
            /// Post方法
            /// </summary>
            /// <param name="url">请求地址</param>
            /// <param name="body">Post内容</param>
            /// <param name="cookieContainer">Cookies存储器</param>
            /// <param name="encoding">返回内容编码</param>
            /// <param name="others">其他需要补充的HTTP协议头</param>
            /// <returns>请求结果</returns>
            public static string Post(string url,
                byte[] body,
                CookieContainer cookieContainer,
                Encoding encoding,
                Dictionary<string, string> others = null)
            {
                return InternalHttp(HttpMethod.POST, url, body, cookieContainer, encoding, others);
            }
    
            /// <summary>
            /// Http操作
            /// </summary>
            /// <param name="method">请求方式</param>
            /// <param name="url">请求地址</param>
            /// <param name="bytes">提交的数据</param>
            /// <param name="cookieContainer">Cookies存储器</param>
            /// <param name="encoding">返回内容编码</param>
            /// <param name="others">其他需要补充的HTTP协议头</param>
            /// <returns>请求结果</returns>
            static string InternalHttp(HttpMethod method,
                string url,
                byte[] bytes,
                CookieContainer cookieContainer,
                Encoding encoding,
                Dictionary<string, string> others = null)
            {
                string result = string.Empty;
                if (string.IsNullOrEmpty(url))
                    throw new ArgumentNullException("请求地址不能为空");
                if (method == HttpMethod.POST)
                {
                    if (bytes == null)
                        throw new ArgumentNullException("提交的数据不能为空");
                }
                if (cookieContainer == null)
                    throw new ArgumentNullException("Cookies存储器不能为空");
                try
                {
                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                    request.Method = method.ToString();
                    request.UserAgent = "Mozilla/5.0 (Windows NT 6.1;MSIE 9.0;)";
                    request.CookieContainer = cookieContainer;
                    if (method == HttpMethod.POST)
                    {
                        request.ContentType = "application/x-www-form-urlencoded";
                        request.ContentLength = bytes.Length;
                        using (Stream stream = request.GetRequestStream())
                        {
                            stream.Write(bytes, 0, bytes.Length);
                            stream.Flush();
                        }
                    }
                    if (others != null)
                    {
                        foreach (KeyValuePair<string, string> pair in others)
                        {
                            request.Headers.Add(pair.Key, pair.Value);
                        }
                    }
                    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        using (StreamReader reader = new StreamReader(response.GetResponseStream(), encoding))
                        {
                            result = reader.ReadToEnd();
                        }
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
                return result;
            }
    
            #endregion
    
            #region Socket
    
            static bool ValidateServerCertificate(
                     object sender,
                     X509Certificate certificate,
                     X509Chain chain,
                     SslPolicyErrors sslPolicyErrors)
            {
                /*
                if (sslPolicyErrors == SslPolicyErrors.None)
                    return true;
                Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
                return false;
                */
                return true;
            }
    
            public static HttpResponse Get(IPEndPoint endpoint,
                HttpHeader header)
            {
                return Get(endpoint, header, null);
            }
    
            public static HttpResponse Get(IPEndPoint endpoint,
                HttpHeader header,
                X509CertificateCollection x509certs)
            {
                return InternalSslSocketHttp(HttpMethod.GET, endpoint, header, x509certs);
            }
    
            public static HttpResponse Post(IPEndPoint endpoint,
                HttpHeader header)
            {
                return Post(endpoint, header, null);
            }
    
            public static HttpResponse Post(IPEndPoint endpoint,
                HttpHeader header,
                X509CertificateCollection x509certs)
            {
                return InternalSslSocketHttp(HttpMethod.POST, endpoint, header, x509certs);
            }
    
            static HttpResponse InternalSslSocketHttp(HttpMethod method,
                IPEndPoint endpoint,
                HttpHeader header,
                X509CertificateCollection x509certs)
            {
                HttpResponse response = null;
                try
                {
                    TcpClient tcp = new TcpClient();
                    tcp.Connect(endpoint);
                    if (tcp.Connected)
                    {
                        byte[] buff = ParseHttpHeaderToBytes(method, header);  //生成协议包
                        if (x509certs != null)
                        {
                            using (SslStream ssl = new SslStream(tcp.GetStream(),
                                                    false,
                                                    new RemoteCertificateValidationCallback(ValidateServerCertificate),
                                                    null))
                            {
                                ssl.AuthenticateAsClient("SslServerName",
                                    x509certs,
                                    SslProtocols.Tls,
                                    false);
                                if (ssl.IsAuthenticated)
                                {
                                    ssl.Write(buff);
                                    ssl.Flush();
                                    response = ReadResponse(ssl);
                                }
                            }
                        }
                        else
                        {
                            using (NetworkStream ns = tcp.GetStream())
                            {
                                ns.Write(buff, 0, buff.Length);
                                ns.Flush();
                                response = ReadResponse(ns);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
                return response;
            }
    
            class TaskArguments
            {
                public TaskArguments(CancellationTokenSource cancelSource, Stream sm)
                {
                    this.CancelSource = cancelSource;
                    this.Stream = sm;
                }
                public CancellationTokenSource CancelSource { get; private set; }
                public Stream Stream { get; private set; }
            }
    
            private static HttpResponse ReadResponse(Stream sm)
            {
                HttpResponse response = null;
                CancellationTokenSource cancelSource = new CancellationTokenSource();
                Task<string> myTask = Task.Factory.StartNew<string>(
                    new Func<object, string>(ReadHeaderProcess),
                    new TaskArguments(cancelSource,sm),
                    cancelSource.Token);
                if (myTask.Wait(3 * 1000)) //尝试3秒时间读取协议头
                {
                    string header = myTask.Result;
                    if (!string.IsNullOrEmpty(header))
                    {
                        if (header.StartsWith("HTTP/1.1 100"))
                        {
                            return ReadResponse(sm);
                        }
                        byte[] buff = null;
                        int start = header.ToUpper().IndexOf("CONTENT-LENGTH");
                        int content_length = -1;  //fix bug
                        if (start > 0)
                        {
                            string temp = header.Substring(start, header.Length - start);
                            string[] sArry = Regex.Split(temp, "
    ");
                            content_length = Convert.ToInt32(sArry[0].Split(':')[1]);
                            if (content_length > 0)
                            {
                                buff = new byte[content_length];
                                int inread = sm.Read(buff, 0, buff.Length);
                                while (inread < buff.Length)
                                {
                                    inread += sm.Read(buff, inread, buff.Length - inread);
                                }
                            }
                        }
                        else
                        {
                            start = header.ToUpper().IndexOf("TRANSFER-ENCODING: CHUNKED");
                            if (start > 0)
                            {
                                buff = ChunkedReadResponse(sm);
                            }
                            else
                            {
                                buff = SpecialReadResponse(sm);//例外
                            }
                        }
                        response = new HttpResponse(header, buff);
                    }
                }
                else
                {
                    cancelSource.Cancel(); //超时的话,别忘记取消任务哦
                }
                return response;
            }
    
            static string ReadHeaderProcess(object args)
            {
                TaskArguments argument = args as TaskArguments;
                StringBuilder bulider = new StringBuilder();
                if (argument != null)
                {
                    Stream sm = argument.Stream;
                    while (!argument.CancelSource.IsCancellationRequested)
                    {
                        try
                        {
                            int read = sm.ReadByte();
                            if (read != -1)
                            {
                                byte b = (byte)read;
                                bulider.Append((char)b);
                                string temp = bulider.ToString();
                                if (temp.EndsWith("
    
    "))//Http协议头尾
                                {
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine(ex.Message);
                            break;
                        }
                    }
                }
                return bulider.ToString();
            }
    
            class ArraySegmentList<T>
            {
                List<ArraySegment<T>> m_SegmentList = new List<ArraySegment<T>>();
                public ArraySegmentList() { }
    
                int m_Count = 0;
                public void Add(ArraySegment<T> arraySegment)
                {
                    m_Count += arraySegment.Count;
                    m_SegmentList.Add(arraySegment);
                }
    
                public T[] ToArray()
                {
                    T[] array = new T[m_Count];
                    int index = 0;
                    for (int i = 0; i < m_SegmentList.Count; i++)
                    {
                        ArraySegment<T> arraySegment = m_SegmentList[i];
                        Array.Copy(arraySegment.Array,
                            0,
                            array,
                            index,
                            arraySegment.Count);
                        index += arraySegment.Count;
                    }
                    return array;
                }
            }
            static byte[] ChunkedReadResponse(Stream sm)
            {
                ArraySegmentList<byte> arraySegmentList = new ArraySegmentList<byte>();
                int chunked = GetChunked(sm);
                while (chunked > 0)
                {
                    byte[] buff = new byte[chunked];
                    try{
                        int inread = sm.Read(buff, 0, buff.Length);
                        while (inread < buff.Length)
                        {
                            inread += sm.Read(buff, inread, buff.Length - inread);
                        }
                        arraySegmentList.Add(new ArraySegment<byte>(buff));
                        if (sm.ReadByte() != -1)//读取段末尾的
    
                        {
                            sm.ReadByte();
                        }
                    }catch(Exception){
                        break;
                    }
                    chunked = GetChunked(sm);
                }
                return arraySegmentList.ToArray();
            }
    
            static int GetChunked(Stream sm)
            {
                int chunked = 0;
                StringBuilder bulider = new StringBuilder();
                while (true)
                {
                    try
                    {
                        int read = sm.ReadByte();
                        if (read != -1)
                        {
                            byte b = (byte)read;
                            bulider.Append((char)b);
                            string temp = bulider.ToString();
                            if (temp.EndsWith("
    "))
                            {
                                chunked = Convert.ToInt32(temp.Trim(), 16);
                                break;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.Message);
                        break;
                    }
                }
                return chunked;
            }
    
            /*
             * 注意:该方法仅供测试,实际使用时请根据需要定制
             */
            static byte[] SpecialReadResponse(Stream sm)
            {
                ArrayList array = new ArrayList();
                StringBuilder bulider = new StringBuilder();
                int length = 0;
                DateTime now = DateTime.Now;
                while (true)
                {
                    byte[] buff = new byte[1024 * 10];
                    int len = sm.Read(buff, 0, buff.Length);
                    if (len > 0)
                    {
                        length += len;
                        byte[] reads = new byte[len];
                        Array.Copy(buff, 0, reads, 0, len);
                        array.Add(reads);
                        bulider.Append(Encoding.Default.GetString(reads));
                    }
                    string temp = bulider.ToString();
                    if (temp.ToUpper().Contains("</HTML>"))
                    {
                        break;
                    }
                    if (DateTime.Now.Subtract(now).TotalSeconds >= 30)
                    {
                        break;//超时30秒则跳出
                    }
                }
                byte[] bytes = new byte[length];
                int index = 0;
                for (int i = 0; i < array.Count; i++)
                {
                    byte[] temp = (byte[])array[i];
                    Array.Copy(temp, 0, bytes,
                        index, temp.Length);
                    index += temp.Length;
                }
                return bytes;
            }
    
            #endregion
    
            #region  Helper
    
            /// <summary>
            /// 将HTTP协议头转换为Bytes数据
            /// </summary>
            /// <param name="method">HTTP方法</param>
            /// <param name="header">HTTP协议头</param>
            /// <returns>Bytes数据</returns>
            static byte[] ParseHttpHeaderToBytes(HttpMethod method, HttpHeader header)
            {
                StringBuilder bulider = new StringBuilder();
                if (method.Equals(HttpMethod.POST))
                {
                    bulider.AppendLine(string.Format("POST {0} HTTP/1.1",
                        header.Url));
                    bulider.AppendLine("Content-Type: application/x-www-form-urlencoded");
                }
                else
                {
                    bulider.AppendLine(string.Format("GET {0} HTTP/1.1",
                    header.Url));
                }
                if (!string.IsNullOrEmpty(header.Host))
                    bulider.AppendLine(string.Format("Host: {0}",
                        header.Host));
                bulider.AppendLine("User-Agent: Mozilla/5.0 (Windows NT 6.1; IE 9.0)");
                if (!string.IsNullOrEmpty(header.Referer))
                    bulider.AppendLine(string.Format("Referer: {0}",
                        header.Referer));
                bulider.AppendLine("Connection: keep-alive");
                if (!string.IsNullOrEmpty(header.Accept))
                {
                    bulider.AppendLine(string.Format("Accept: {0}",
                     header.Accept));
                }
                else
                {
                    bulider.AppendLine("Accept: */*");
                }
                if (!string.IsNullOrEmpty(header.Cookies))
                    bulider.AppendLine(string.Format("Cookie: {0}",
                        header.Cookies));
                if (method.Equals(HttpMethod.POST))
                {
                    bulider.AppendLine(string.Format("Content-Length: {0}
    ",
                       Encoding.Default.GetBytes(header.Body).Length));
                    bulider.Append(header.Body);
                }
                else
                {
                    bulider.Append("
    ");
                }
                return Encoding.Default.GetBytes(bulider.ToString());
            }
    
            /// <summary>
            /// 从Url中提取Host信息
            /// </summary>
            /// <param name="url">Url</param>
            /// <returns>Host信息</returns>
            public static string GetHost(string url)
            {
                string host = string.Empty;
                try
                {
                    Uri uri = new Uri(url);
                    host = uri.Host;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
                return host;
            }
    
            /// <summary>
            /// 通过Host获取IP地址
            /// </summary>
            /// <param name="host">Host</param>
            /// <returns>IP地址</returns>
            public static IPAddress GetAddress(string host)
            {
                IPAddress address = IPAddress.Any;
                try
                {
                    IPAddress[] alladdress = Dns.GetHostAddresses(host);
                    if (alladdress.Length > 0)
                    {
                        address = alladdress[0];
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
                return address;
            }
    
            /// <summary>
            /// 从HTTP返回头协议中取Set-Cookie信息(即Cookies)
            /// </summary>
            /// <param name="responseHeader">HTTP返回头协议</param>
            /// <returns>Cookies</returns>
            public static string GetCookies(string responseHeader)
            {
                StringBuilder cookies = new StringBuilder();
                using (StringReader reader = new StringReader(responseHeader))
                {
                    string strLine = reader.ReadLine();
                    while (strLine != null)
                    {
                        if (strLine.StartsWith("Set-Cookie:"))
                        {
                            string temp = strLine.Remove(0, 12);
                            if (!temp.EndsWith(";"))
                            {
                                temp = temp + ";";
                            }
                            cookies.Append(temp);
                        }
                        strLine = reader.ReadLine();
                    }
                }
                return cookies.ToString();
            }
    
            /// <summary>
            /// 从HTTP返回头协议中去Location地址(一般出现在301跳转)
            /// </summary>
            /// <param name="responseHeader">HTTP返回头协议</param>
            /// <returns>Location地址</returns>
            public static string GetLocation(string responseHeader)
            {
                string result = string.Empty;
                using (StringReader reader = new StringReader(responseHeader))
                {
                    string strLine = reader.ReadLine();
                    while (strLine != null)
                    {
                        if (strLine.StartsWith("Location:"))
                        {
                            result = strLine.Remove(0, 10);
                        }
                        strLine = reader.ReadLine();
                    }
                }
                return result;
            }
    
            #endregion
        }
    }
  • 相关阅读:
    CVTE前端一面
    转载几篇看过的几篇使用技术博文
    Vue自定义指令
    node项目初始化的一些配置
    vue+element 实现在表格内插入其他组件,每行数据独立存储
    jquery如何实现当页面下拉到一定位置时,右下角出现回到顶部图标
    css实现垂直居中的方法整理
    css3兼容性检测工具
    css变换与动画详解
    手机访问电脑端网站偏问题解决
  • 原文地址:https://www.cnblogs.com/wangchuang/p/5138300.html
Copyright © 2011-2022 走看看