C# 如何将代理与TcpClient.ConnectAsync()一起使用?
NET中的HTTP代理支持实际上不支持较低级别的类,如TcpClient或Socket。但我想通过支持“connect”命令的HTTP代理连接TCPServer(ip、端口) 因此,我需要执行以下步骤:C# 如何将代理与TcpClient.ConnectAsync()一起使用?,c#,.net,networking,proxy,tcpclient,C#,.net,Networking,Proxy,Tcpclient,NET中的HTTP代理支持实际上不支持较低级别的类,如TcpClient或Socket。但我想通过支持“connect”命令的HTTP代理连接TCPServer(ip、端口) 因此,我需要执行以下步骤: 连接到代理服务器 发送连接主机:端口HTTP/1.1 发送 等待回应。如果它包含HTTP/1.X 200,则连接成功 进一步阅读响应行,直到收到空行 它通过代理连接到外部世界。任何可能与代理进行的数据交换 事实上,我是在没有代理的情况下做这件事的 TcpClient _client;
连接主机:端口HTTP/1.1
HTTP/1.X 200
,则连接成功 TcpClient _client;
NetworkStream _stream;
public static async Task<bool> ConnectAsync(string hostname, int port)
{
_client = new TcpClient();
await _client.ConnectAsync(hostname, port).ConfigureAwait(false);
_stream = conn._client.GetStream();
..... Do some stuff
// Connexion OK
return true;
}
TcpClient\u客户端;
网络流(NetworkStream);;
公共静态异步任务ConnectAsync(字符串主机名,int端口)
{
_client=新的TcpClient();
await\u client.ConnectAsync(主机名、端口)。ConfigureAwait(false);
_stream=conn._client.GetStream();
……做点什么
//连接正常
返回true;
}
如何在连接TcpClient之前使用代理和凭据?我找到了一个基于和的解决方案
TcpClient\u客户端;
网络流(NetworkStream);;
公共TcpClient ProxyTcpClient(字符串targetHost、int targetPort、字符串httpProxyHost、int httpProxyPort、字符串proxyUserName、字符串proxyPassword)
{
const BindingFlags Flags=BindingFlags.NonPublic | BindingFlags.Instance;
Uri proxyUri=新的UriBuilder
{
Scheme=Uri.UriSchemeHttp,
主机=httpProxyHost,
端口=httpProxyPort
}.Uri;
Uri targetUri=新的UriBuilder
{
Scheme=Uri.UriSchemeHttp,
主机=目标主机,
端口=目标端口
}.Uri;
WebProxy WebProxy=新的WebProxy(proxyUri,true);
webProxy.Credentials=新的网络凭据(代理用户名、代理密码);
WebRequest=WebRequest.Create(targetUri);
Proxy=webProxy;
request.Method=“CONNECT”;
HttpWebResponse=(HttpWebResponse)request.GetResponse();
Stream responseStream=response.GetResponseStream();
类型responseType=responseStream.GetType();
PropertyInfo connectionProperty=responseType.GetProperty(“连接”,标志);
var connection=connectionProperty.GetValue(responseStream,null);
类型connectionType=connection.GetType();
PropertyInfo networkStreamProperty=connectionType.GetProperty(“NetworkStream”,标志);
NetworkStream NetworkStream=(NetworkStream)networkStreamProperty.GetValue(connection,null);
类型nsType=networkStream.GetType();
PropertyInfo-socketProperty=nsType.GetProperty(“套接字”,标志);
Socket套接字=(Socket)socketProperty.GetValue(networkStream,null);
返回新的TcpClient{Client=socket};
}
公共静态异步任务ConnectAsync(字符串主机名,int端口)
{
_client=ProxyTcpClient(“IPTargetHost”,1234,“IPProxyHost”,5678,“Userproxy”,“Userppwd”);
_stream=conn._client.GetStream();
……做点什么
//连接正常
返回true;
}
我们已经设法使用.Net的套接字实现了它。调用Nuget包。代码非常简单:
public static TcpClient CreateProxied(Uri proxy, Uri destination)
{
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(proxy.Host, proxy.Port);
var connectMessage = Encoding.UTF8.GetBytes($"CONNECT {destination.Host}:{destination.Port} HTTP/1.1{Environment.NewLine}{Environment.NewLine}");
socket.Send(connectMessage);
byte[] receiveBuffer = new byte[1024];
var received = socket.Receive(receiveBuffer);
var response = ASCIIEncoding.ASCII.GetString(receiveBuffer, 0, received);
if (!response.Contains("200 OK"))
{
throw new Exception($"Error connecting to proxy server {destination.Host}:{destination.Port}. Response: {response}");
}
return new TcpClient
{
Client = socket
};
}
此处投稿:若代理需要基本身份验证,则要扩展答案,请将标题添加到连接消息中
var auth = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{proxy.Login}:{proxy.Password}"));
var connectMessage = Encoding.UTF8.GetBytes($"CONNECT {host}:{port} HTTP/1.1\nProxy-Authorization: Basic {auth}\n\n");
socket.Send(connectMessage);
这个解决方案似乎有点黑。。。有没有其他方法可以在不使用反射的情况下设置代理?
var auth = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{proxy.Login}:{proxy.Password}"));
var connectMessage = Encoding.UTF8.GetBytes($"CONNECT {host}:{port} HTTP/1.1\nProxy-Authorization: Basic {auth}\n\n");
socket.Send(connectMessage);