2017-08-05 16 views
6

Ich verbinde mich mit einem Proxy und mit dem Befehl connect sende ich einige benutzerdefinierte Header. Dies ist eine Voraussetzung. Ich bekomme eine 200 Antwort. Dann versuche ich, die gleiche Verbindung zu verwenden, um eine get-Anfrage zu machen (Suche angehängt Code für "GET {0}"), aber ich bekomme immer einen Fehler, der endet "Verbindung geschlossen" (kann nicht den genauen Fehler von Hand aufrufen). ESSENTIELL Ich muss tunnel zu einem websit wie https: \ www.omesecuresite.com Heres der Code. Bestimmte Teile wurden für Breviaty ausgeschlossen.So halten Sie die Verbindung beim HTTP-Tunneling offen

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; 
     } 
    } 
}   
+1

Reagiert der Server mit einem Header von 'Connection: keep-alive'? Wenn nicht, dann wird es wahrscheinlich nicht unterstützt. –

+1

Gibt es auch einen Grund, warum Sie das manuell tun und 'System.Net.WebRequest' nicht verwenden? –

+1

[This] (https://stackoverflow.com/questions/19155201/http-keep-alive-timeout) könnte hilfreich sein. – Shanky

Antwort

10

Http-Verbindung nahe kommt aufgrund ihrer Art von Autoschließ Verbindung nach bestimmtem Zeitpunkt gibt es nicht viel können Sie auseinander tun von steigenden autclosing Dauer für die Verbindung, die wiederum ist abhängig von Server zu Server. was in Verbindung endet, endet am Ende.

FTP-Verbindung Wenn Sie Daten hochladen oder herunterladen möchten, die viel Zeit benötigen, verwenden Sie besser die FTP-Verbindung, die nur aus dem gleichen Grund existiert.

6

Abhängig von der Art Ihrer Header können Sie WebSockets verwenden, da Sie custom authorization headers senden können.

Da WebSocket verwendet werden soll, wenn die gleiche Verbindung die Vollduplex-Kommunikation (sowohl Herunterladen als auch Hochladen von Daten) zulassen soll, ist es geeigneter als eine HTTP-Verbindung.

Verwandte Themen