HTTP CONNECT stream.ReadToEnd 需要无限时间
HTTP CONNECT stream.ReadToEnd takes infinite time
我正在尝试构建一个应该能够使用 HTTP CONNECT 代理隧道的 class。
我当前的代码挂在 DoHttpConnect() - "var retvar = await sr.ReadToEndAsync();"
并且从未到达 Console.WriteLine(retvar);
连接class:
public class HttpConnect : BaseProxyModule
{
public HttpConnect(HostPortCollection proxyInformation) : base(proxyInformation)
{
}
public override async Task<Stream> OpenStreamAsync(HostPortCollection dstSrv)
{
var socket = new TcpClient();
if (await SwallowExceptionUtils.TryExec(() => socket.ConnectAsync(_proxyInformation.Addr, _proxyInformation.Port)) && socket.Connected)
{
var nStream = socket.GetStream();
var cmd = ProxyCommandBuildUtils.GenerateHttpConnectCommand(dstSrv.Host, dstSrv.Port);
await nStream.WriteAsync(cmd, 0, cmd.Length);
var sr = new StreamReader(nStream);
var cLine = await sr.ReadLineAsync();
var fLineElem = cLine.Split(' ');
if (fLineElem.Length >= 1 && fLineElem[1] == "200")
{
await sr.ReadLineAsync();
return nStream;
}
}
return null;
}
internal class ProxyCommandBuildUtils
{
private const string HTTP_PROXY_CONNECT_CMD = "CONNECT {0}:{1} HTTP/1.1\r\nHost: {0}\r\n\r\n";
public static byte[] GenerateHttpConnectCommand(string host, int port)
{
string connectCmd = String.Format(CultureInfo.InvariantCulture, HTTP_PROXY_CONNECT_CMD, host, port.ToString(CultureInfo.InvariantCulture));
return connectCmd.GetBytes();
}
}
用法:
public static void Main(string[] args)
{
DoHttpConnect().Wait();
Debugger.Break();
}
public static async Task DoHttpConnect()
{
//var hCon = new HttpConnect(new HostPortCollection("5.135.195.166", 3128)); //Doesn't work..
var hCon = new HttpConnect(new HostPortCollection("109.75.213.146", 53281)); //Doesn't work either :/
var pStream = await hCon.OpenStreamAsync(new HostPortCollection("www.myip.ch", 80));
var request = FormatHttpRequest(new Uri("http://www.myip.ch/"));
using (var sw = new StreamWriter(pStream))
using (var sr = new StreamReader(pStream))
{
await sw.WriteLineAsync(request);
var retvar = await sr.ReadToEndAsync(); //Takes till the end of time itself
Console.WriteLine(retvar);
}
Debugger.Break();
}
private static string FormatHttpRequest(Uri url)
{
return $"GET {url.LocalPath} HTTP/1.0\r\nHost: {url.DnsSafeHost}\r\n\r\n";
}
WriteLineAsync()
调用实际上并没有立即写入网络。相反,StreamWriter
将其保存在缓冲区中。因此,服务器从未真正收到您的请求,因此不会向您发送回复。
您应该通过执行以下操作之一强制缓冲区写出到网络:
- 为
StreamWriter
开启 AutoFlush
(reference),这将使它在每次调用 WriteLineAsync()
时刷新缓冲区
- 显式调用
FlushAsync()
(reference)
通过重写如下代码关闭流(这将刷新缓冲区):
using (var sr = new StreamReader(pStream))
{
using (var sw = new StreamWriter(pStream))
{
await sw.WriteLineAsync(request);
}
var retvar = await sr.ReadToEndAsync();
Console.WriteLine(retvar);
}
我正在尝试构建一个应该能够使用 HTTP CONNECT 代理隧道的 class。
我当前的代码挂在 DoHttpConnect() - "var retvar = await sr.ReadToEndAsync();"
并且从未到达 Console.WriteLine(retvar);
连接class:
public class HttpConnect : BaseProxyModule
{
public HttpConnect(HostPortCollection proxyInformation) : base(proxyInformation)
{
}
public override async Task<Stream> OpenStreamAsync(HostPortCollection dstSrv)
{
var socket = new TcpClient();
if (await SwallowExceptionUtils.TryExec(() => socket.ConnectAsync(_proxyInformation.Addr, _proxyInformation.Port)) && socket.Connected)
{
var nStream = socket.GetStream();
var cmd = ProxyCommandBuildUtils.GenerateHttpConnectCommand(dstSrv.Host, dstSrv.Port);
await nStream.WriteAsync(cmd, 0, cmd.Length);
var sr = new StreamReader(nStream);
var cLine = await sr.ReadLineAsync();
var fLineElem = cLine.Split(' ');
if (fLineElem.Length >= 1 && fLineElem[1] == "200")
{
await sr.ReadLineAsync();
return nStream;
}
}
return null;
}
internal class ProxyCommandBuildUtils
{
private const string HTTP_PROXY_CONNECT_CMD = "CONNECT {0}:{1} HTTP/1.1\r\nHost: {0}\r\n\r\n";
public static byte[] GenerateHttpConnectCommand(string host, int port)
{
string connectCmd = String.Format(CultureInfo.InvariantCulture, HTTP_PROXY_CONNECT_CMD, host, port.ToString(CultureInfo.InvariantCulture));
return connectCmd.GetBytes();
}
}
用法:
public static void Main(string[] args)
{
DoHttpConnect().Wait();
Debugger.Break();
}
public static async Task DoHttpConnect()
{
//var hCon = new HttpConnect(new HostPortCollection("5.135.195.166", 3128)); //Doesn't work..
var hCon = new HttpConnect(new HostPortCollection("109.75.213.146", 53281)); //Doesn't work either :/
var pStream = await hCon.OpenStreamAsync(new HostPortCollection("www.myip.ch", 80));
var request = FormatHttpRequest(new Uri("http://www.myip.ch/"));
using (var sw = new StreamWriter(pStream))
using (var sr = new StreamReader(pStream))
{
await sw.WriteLineAsync(request);
var retvar = await sr.ReadToEndAsync(); //Takes till the end of time itself
Console.WriteLine(retvar);
}
Debugger.Break();
}
private static string FormatHttpRequest(Uri url)
{
return $"GET {url.LocalPath} HTTP/1.0\r\nHost: {url.DnsSafeHost}\r\n\r\n";
}
WriteLineAsync()
调用实际上并没有立即写入网络。相反,StreamWriter
将其保存在缓冲区中。因此,服务器从未真正收到您的请求,因此不会向您发送回复。
您应该通过执行以下操作之一强制缓冲区写出到网络:
- 为
StreamWriter
开启AutoFlush
(reference),这将使它在每次调用WriteLineAsync()
时刷新缓冲区
- 显式调用
FlushAsync()
(reference) 通过重写如下代码关闭流(这将刷新缓冲区):
using (var sr = new StreamReader(pStream)) { using (var sw = new StreamWriter(pStream)) { await sw.WriteLineAsync(request); } var retvar = await sr.ReadToEndAsync(); Console.WriteLine(retvar); }