zoukankan      html  css  js  c++  java
  • C# HttpTunnelClient

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Diagnostics.Contracts;
    using System.Collections.Specialized;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Net.Security;
    using System.Net.Mime;
    using System.Reflection;
    
    namespace Rocky.Net
    {
        public class HttpTunnelClient
        {
            #region Fields
            private HttpRequestEntity _entity;
            private SocketProxy _proxy;
            private Socket _sock;
            #endregion
    
            #region Properties
            public WebHeaderCollection Headers
            {
                get { return _entity.Headers; }
            }
            public NameValueCollection Form
            {
                get { return _entity.Form; }
            }
            public bool KeepAlive { get; set; }
            public bool HeadMethod { get; set; }
            public int SendReceiveTimeout { get; set; }
            #endregion
    
            #region Constructors
            public HttpTunnelClient(Uri proxyAddress = null)
            {
                if (proxyAddress != null)
                {
                    _proxy = new SocketProxy()
                    {
                        ProxyType = SocketProxyType.ptHTTP,
                        Address = SocketHelper.ParseEndPoint(proxyAddress.GetEndPoint())
                    };
                }
                _entity = new HttpRequestEntity();
                _entity.Headers[HttpRequestHeader.Accept] = "*/*";
                _entity.Headers[HttpRequestHeader.Referer] = HttpClient.DefaultReferer;
                _entity.Headers[HttpRequestHeader.UserAgent] = HttpClient.DefaultUserAgent;
                this.KeepAlive = true;
                this.SendReceiveTimeout = 1000 * 30;
            }
            #endregion
    
            #region Methods
            private void Prepare(out string method, out string sForm)
            {
                method = sForm = null;
                _entity.Headers["Proxy-Connection"] = _entity.Headers[HttpRequestHeader.Connection] = this.KeepAlive ? "keep-alive" : "close";
                if (this.HeadMethod)
                {
                    method = WebRequestMethods.Http.Head;
                    return;
                }
                if (!_entity.HasValue)
                {
                    method = WebRequestMethods.Http.Get;
                    return;
                }
                sForm = _entity.GetFormString();
                _entity.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
                _entity.Headers[HttpRequestHeader.ContentLength] = Encoding.UTF8.GetByteCount(sForm).ToString();
                method = WebRequestMethods.Http.Post;
            }
    
            private void SetEncoding(StreamReader reader, Encoding encoding, out string bufferedString)
            {
                Type type = reader.GetType();
                var flags = BindingFlags.NonPublic | BindingFlags.Instance;
                var field = type.GetField("charPos", flags);
                int charPos = Convert.ToInt32(field.GetValue(reader));
                field = type.GetField("charLen", flags);
                int charLen = Convert.ToInt32(field.GetValue(reader));
                field = type.GetField("byteBuffer", flags);
                byte[] byteBuffer = (byte[])field.GetValue(reader);
                bufferedString = encoding.GetString(byteBuffer, charPos, charLen - charPos);
    
                field = type.GetField("encoding", flags);
                field.SetValue(reader, encoding);
    
                field = type.GetField("decoder", flags);
                field.SetValue(reader, encoding.GetDecoder());
    
                reader.DiscardBufferedData();
            }
    
            public HttpResponseEntity GetResponse(Uri requestUri, Action<Stream> onSend = null, Action<Stream> onReceive = null)
            {
                Contract.Requires(requestUri != null);
    
                _entity.Headers[HttpRequestHeader.Host] = requestUri.Host;
                string method, sForm;
                this.Prepare(out method, out sForm);
    
                _sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _sock.ReceiveTimeout = _sock.SendTimeout = this.SendReceiveTimeout;
                try
                {
                    if (_proxy != null)
                    {
                        _sock.Connect(_proxy.Address);
                        byte[] data = ProxyUtility.PrepareRequest(_proxy, SocketHelper.ParseEndPoint(requestUri.GetEndPoint()));
                        int sent = _sock.Send(data);
                        Array.Resize(ref data, 256);
                        int recv = _sock.Receive(data);
                        ProxyUtility.ValidateResponse(_proxy, data);
                    }
                    else
                    {
                        _sock.ConnectSync(requestUri.Host, requestUri.Port);
                    }
    
                    var netStream = new NetworkStream(_sock, FileAccess.ReadWrite, false);
                    Stream src = netStream;
                    if (requestUri.Scheme == Uri.UriSchemeHttps)
                    {
                        var sslStream = new SslStream(src);
                        sslStream.AuthenticateAsClient(requestUri.Host);
                        src = sslStream;
                    }
    
                    var writer = new StreamWriter(src, Encoding.ASCII);
                    writer.WriteLine("{0} {1} HTTP/1.1", method, requestUri.PathAndQuery);
                    var sHeaders = new StringBuilder(_entity.GetHeadersString());
                    SocketHelper.Logger.DebugFormat("RequestHeaders:\r\n{0}\r\n", sHeaders);
                    writer.WriteLine(sHeaders);
                    writer.WriteLine();
                    writer.Flush();
                    if (onSend != null)
                    {
                        onSend(src);
                    }
                    else
                    {
                        if (sForm != null)
                        {
                            writer = new StreamWriter(src, Encoding.UTF8);
                            writer.Write(sForm);
                            writer.Flush();
                        }
                    }
    
                    var response = new HttpResponseEntity();
                    var reader = new StreamReader(src, Encoding.ASCII);
                    //HTTP/1.1 200 OK
                    string line = reader.ReadLine();
                    var status = line.Split(new char[] { ' ' }, 3);
                    if (status.Length != 3)
                    {
                        throw new WebException("InternalServerError");
                    }
                    response.StatusCode = (HttpStatusCode)int.Parse(status[1]);
                    response.StatusDescription = status[2];
                    sHeaders.Length = 0;
                    while (!string.IsNullOrEmpty(line = reader.ReadLine()))
                    {
                        int i = line.IndexOf(":");
                        string name = line.Substring(0, i), value = line.Substring(i + 2);
                        response.Headers.Add(name, value);
                        sHeaders.AppendLine(line);
                    }
                    SocketHelper.Logger.DebugFormat("ResponseHeaders:\r\n{0}\r\n", sHeaders);
                    string contentType = response.Headers[HttpResponseHeader.ContentType];
                    int charsetIndex;
                    if (string.IsNullOrEmpty(contentType) || (charsetIndex = contentType.LastIndexOf("=")) == -1)
                    {
                        response.ContentEncoding = Encoding.UTF8;
                    }
                    else
                    {
                        string charset = contentType.Substring(charsetIndex + 1);
                        response.ContentEncoding = Encoding.GetEncoding(charset);
                    }
                    if (!this.HeadMethod)
                    {
                        if (onReceive != null)
                        {
                            onReceive(src);
                        }
                        else
                        {
                            string bufferedString;
                            this.SetEncoding(reader, response.ContentEncoding, out bufferedString);
                            response.ResponseText = bufferedString;
                            response.ResponseText += reader.ReadToEnd();
                        }
                    }
                    return response;
                }
                finally
                {
                    _entity.Clear(HttpRequestEntity.ItemKind.Form);
                    if (_sock.Connected)
                    {
                        _sock.Disconnect(this.KeepAlive);
                    }
                }
            }
            #endregion
        }
    }
    

      

  • 相关阅读:
    C3P0连接池详解及配置
    解决a different object with the same identifier value was already associated with the session错误
    sudo su 提示没有配置JDK environment
    MySQL 5.6 双机热备
    如何用myeclispe远程调试tomcat
    Incorrect string value: '\xF0\xA1\xA1\x92' for column 'herst' at row 1
    Mysql 慢查询设置
    Mysql的主从数据库没有同步的解决办法
    新的启程
    ASP.NET程序中常用的三十三种代码
  • 原文地址:https://www.cnblogs.com/Googler/p/3024534.html
Copyright © 2011-2022 走看看