通过Http代理服务器连接TCP的更好方法

时间:2019-01-18 04:58:27

标签: c# tcp http-proxy

我们需要连接tcp服务器并在代理后面建立tcp连接(大多数防火墙会阻止直接tcp连接到特定端口)。

因此,我们实现了Apache http代理服务器,并通过HTTP代理服务器使用HTTP CONNECT METHOD连接了tcp。

因此,我们需要执行以下步骤:

  • 连接到代理。
  • 发送CONNECT Host:Port HTTP/1.1<CR><LF>
  • 发送<CR><LF>
  • 等待响应。如果包含HTTP/1.X 200,则说明连接成功

  • 阅读更多响应行,直到收到空白行。

  • 它通过代理连接到外界

我在下面找到了某人编写的两个代码来完成此任务。

我的问题:在代理后面建立TCP连接的最佳方法是什么?我应该使用Webrequest还是通过TCP套接字使用哪种方法?

public static class HttpProxy
{
    public static TcpClient connectViaHTTPProxyMethod1(
    string targetHost,
    int targetPort,
    string httpProxyHost, 
    int httpProxyPort,
    string proxyUserName,
    string proxyPassword)
    {
        UriBuilder uriBuilder = null;
        Uri proxyUri = null;
        if (httpProxyHost != "")
        {
            uriBuilder = new UriBuilder
            {
                Scheme = Uri.UriSchemeHttp,
                Host = httpProxyHost,
                Port = httpProxyPort
            };

            proxyUri = uriBuilder.Uri;
        }
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
            "http://" + targetHost + ":" + targetPort);
        //request.Timeout = 1000 * 60 * 60;
        request.KeepAlive = false;
        var webProxy = new WebProxy(proxyUri);
        if (httpProxyHost != "")
            request.Proxy = webProxy;
        request.Method = "CONNECT";

        var credentials = new NetworkCredential(
            proxyUserName, proxyPassword);

        if (proxyUserName != "")
            webProxy.Credentials = credentials;

        var response = request.GetResponse();

        var responseStream = response.GetResponseStream();
        Debug.Assert(responseStream != null);

        const BindingFlags Flags = BindingFlags.NonPublic | BindingFlags.Instance;

        var rsType = responseStream.GetType();
        var connectionProperty = rsType.GetProperty("Connection", Flags);

        var connection = connectionProperty.GetValue(responseStream, null);
        var connectionType = connection.GetType();
        var networkStreamProperty = connectionType.GetProperty("NetworkStream", Flags);

        var networkStream = networkStreamProperty.GetValue(connection, null);
        var nsType = networkStream.GetType();
        var socketProperty = nsType.GetProperty("Socket", Flags);
        var socket = (Socket)socketProperty.GetValue(networkStream, null);

        return new TcpClient { Client = socket };
    }

    public static TcpClient connectViaHTTPProxyMethod2(string targetHost, int targetPort, string httpProxyHost, int httpProxyPort, string proxyUserName, string proxyPassword)
    {
        byte[] buffer = new byte[2048];
        int bytes;

        // Connect socket
        // Dnt know how to implement proxyUserName proxyPassword
        TcpClient client = new TcpClient(httpProxyHost, httpProxyPort);
        NetworkStream stream = client.GetStream();

        // Establish Tcp tunnel
        byte[] tunnelRequest = Encoding.UTF8.GetBytes(String.Format("CONNECT {0}:{1} HTTP/1.1\r\nHost:{0}\r\n\r\n", targetHost, targetPort));
        stream.Write(tunnelRequest, 0, tunnelRequest.Length);
        stream.Flush();

        // Read response to CONNECT request
        bytes = stream.Read(buffer, 0, buffer.Length);

        return client;

    }      
}

0 个答案:

没有答案