Как сохранить соединение открытым при выполнении HTTP-туннелирования

Я подключаюсь к прокси-серверу и с помощью команды подключения отправляю некоторые пользовательские заголовки. Это требование. Я получаю ответ 200. Затем я пытаюсь использовать то же соединение для выполнения запроса на получение (ищите прикрепленный код для «GET {0}»), но я всегда получаю сообщение об ошибке, которое заканчивается «соединение закрыто» (не могу вспомнить точную ошибку навскидку). по сути, мне нужно подключиться к веб-сайту, например https:\www.somesecuresite.com. Вот код. Некоторые части были исключены для краткости.

using (TcpClient client = new TcpClient(proxy, proxyPort))
            {
                using (NetworkStream stream = client.GetStream())
                {
                    string EncodedData = encodeUIDPWD(UserName, Password);
                    #region Establish Tcp tunnel

                    string reqString = "CONNECT {0}:{1} HTTP/1.1\r\nProxy-Authorization:Basic " + EncodedData + "\r\nHost: {2}:{3}\r\n";
                    reqString += "Proxy-Connection: keep-alive\r\n";
                    reqString += "Connection: keep-alive\r\n";
                    reqString += "Header1: " + header1 + "\r\n";
                    reqString += "Header2: " + header2 + "\r\n"; 
                    reqString += "None: " + None + "\r\n\r\n";

                    string rString = String.Format(reqString, myUri.Host, myUri.Port, myUri.Host, myUri.Port);
                    #endregion
                    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
                    string reqConnectResult = await DoRequest(myUri, stream, rString);

                    lines.AddRange(reqConnectResult.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).ToList());

                    if (!lines[0].Contains("200"))
                    {
                         //Error code gets caterd for here e.g 503 etc
                    }
                    else
                    {
                        foreach (string line in lines)
                        {
                            if (line.Contains("X-ProxyMesh-IP: "))
                            {
                                ip = line.Replace("X-ProxyMesh-IP: ", string.Empty);
                            }
                        }

                        string reqString1 = "GET {0} HTTP/1.1\r\nHost: {1}:{2}\r\n";
                        reqString1 += "Proxy-Connection: keep-alive\r\n";
                        reqString1 += "Connection: keep-alive\r\n\r\n";

                        string rString1 = string.Format(reqString1, myUri.PathAndQuery, myUri.Host, myUri.Port);
                        string reqPageResult = await DoRequest(myUri, stream, rString1);


                        lines.AddRange(reqPageResult.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).ToList());
                        response.Content = new StringContent(lines.ToString());

                        if (lines[0].Contains("200"))
                        { 
                            return new Tuple<bool, HttpResponseMessage>(true, response);
                        }
                        else
                        {
                            return new Tuple<bool, HttpResponseMessage>(false, response);
                        }
                    }
                }
            }

 private async Task<string> DoRequest(Uri myUri, NetworkStream stream, string reqString)
{

    byte[] tunnelRequest = Encoding.UTF8.GetBytes(reqString);

    await stream.WriteAsync(tunnelRequest, 0, tunnelRequest.Length);
    await stream.FlushAsync();


    using (var memory = new MemoryStream())
    {
        await stream.CopyToAsync(memory);

        memory.Position = 0;
        var data = memory.ToArray();

        //Basically just gets the header part.
        int bm = BinaryMatch(data, Encoding.ASCII.GetBytes("\r\n\r\n"));
        var index = bm + 4;
        if (bm == -1)
        {
            index = 0;
        }

        var headers = Encoding.ASCII.GetString(data, 0, index);
        memory.Position = index;

        Console.WriteLine(headers);
        if (headers.IndexOf("Content-Encoding: gzip") > 0)
        {
            using (GZipStream decompressionStream = new GZipStream(memory, CompressionMode.Decompress))
            using (var decompressedMemory = new MemoryStream())
            {
                decompressionStream.CopyTo(decompressedMemory);
                decompressedMemory.Position = 0;
                string s = (Encoding.UTF8.GetString(decompressedMemory.ToArray()));
                Console.WriteLine(s);

                return headers + s;
            }
        }
        else
        {
            string s = (Encoding.UTF8.GetString(data, index, data.Length - index));
            Console.WriteLine(s);

            return headers + s;
        }
    }
}           

person Eminem    schedule 05.08.2017    source источник
comment
Сервер отвечает заголовком Connection: keep-alive? Если нет, то он, вероятно, не поддерживает его.   -  person Michael Coxon    schedule 10.08.2017
comment
Также есть ли причина, по которой вы делаете это вручную, а не используете System.Net.WebRequest?   -  person Michael Coxon    schedule 10.08.2017
comment
Это может оказаться полезным.   -  person Vivek Shankar    schedule 14.08.2017


Ответы (2)


Http-соединение приближается из-за своей природы автоматического закрытия соединения через определенное время, вы мало что можете сделать, кроме увеличения продолжительности автоматического закрытия для соединения, которое снова зависит от сервера к серверу. что заканчивается тайм-аутом соединения в конце.

FTP-соединение, если вы хотите загружать или скачивать данные, которые требуют чертовски много времени, лучше используйте FTP-соединение, которое существует только по той же причине.

person Vijay Parmar    schedule 08.08.2017