我们需要连接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;
}
}