HTTP library using TcpClient in c#
If you’re looking at TcpClient to make HTTP requests, without totally exhausting the functionality of HttpWebRequest or WebClient, then you’re making a massive mistake. However, in my case, I had to deal with the case where a website required a cookie with a comma in it, which is against the HTTP protocol, and thus an illegal action when trying to construct a new System.Net.Cookie object, I was therefore forced to a lower level, and use TCP/IP to simulate my HTTP stream.
Starting with the lowest level, my TCP/IP stream is handled through this function, which has HTTPS handling built-in:
private static string SendWebRequest(string url, string request, bool isHttps)
{
using (var tc = new TcpClient())
{
tc.Connect(url, isHttps ? 443 : 80);
using (var ns = tc.GetStream())
{
if (isHttps)
{
// Secure HTTP
using (var ssl = new SslStream(ns, false, ValidateServerCertificate, null))
{
ssl.AuthenticateAsClient(url, null, SslProtocols.Tls, false);
using (var sw = new System.IO.StreamWriter(ssl))
{
using (var sr = new System.IO.StreamReader(ssl))
{
sw.Write(request);
sw.Flush();
return sr.ReadToEnd();
}
}
}
}
// Normal HTTP
using (var sw = new System.IO.StreamWriter(ns))
{
using (var sr = new System.IO.StreamReader(ns))
{
sw.Write(request);
sw.Flush();
return sr.ReadToEnd();
}
}
}
}
}
The SSL handling requires the following delegate to be defined, which simply accepts all server certs
// The following method is invoked by the RemoteCertificateValidationDelegate.
private static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
return true; // Accept all certs
}
Then, my GET and POST methods were as follows:
/// <summary>
/// Requests the specified URL.
/// </summary>
/// <param name=”url”>The URL.</param>
/// <param name=”cookies”>The cookies.</param>
/// <returns></returns>
public string Request(string url, List<string> cookies )
{
var lCookieValues = cookies.Select(cookie => cookie.Left(cookie.IndexOf(“;”, StringComparison.Ordinal))).ToArray();
var strCookieValues = String.Join(“;”, lCookieValues);
var address = new Uri(url);
var strHttpRequest = “GET ” + address.PathAndQuery + ” HTTP/1.1\r\n”;
strHttpRequest += “Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*\r\n”;
strHttpRequest += “Accept-Language: en-US\r\n”;
strHttpRequest += “User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)\r\n”;
strHttpRequest += “Cookie: ” + strCookieValues + “\r\n”;
strHttpRequest += “Connection: close\r\n”;
strHttpRequest += “Host: ” + address.Host + “\r\n\r\n”;return SendWebRequest(address.Host, strHttpRequest, address.Scheme == Uri.UriSchemeHttps);
}
Then the POST request is as follows:
/// <summary>
/// Requests the specified URL.
/// </summary>
/// <param name=”url”>The URL.</param>
/// <param name=”postdata”>The post data.</param>
/// <param name=”cookies”>The cookies.</param>
/// <returns></returns>
public string Request(string url, string postdata, List<string> cookies)
{
var lCookieValues = cookies.Select(cookie => cookie.Left(cookie.IndexOf(“;”, StringComparison.Ordinal))).ToArray();
var strCookieValues = String.Join(“;”, lCookieValues);
var address = new Uri(url);
var strHttpRequest = “POST ” + address.PathAndQuery + ” HTTP/1.1\r\n”;
strHttpRequest += “Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*\r\n”;
strHttpRequest += “Accept-Language: en-US\r\n”;
strHttpRequest += “User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)\r\n”;
strHttpRequest += “Cookie: ” + strCookieValues + “\r\n”;
strHttpRequest += “Connection: close\r\n”;
strHttpRequest += “Content-Type: application/x-www-form-urlencoded\r\n”;
strHttpRequest += “Content-Length: “+ postdata.Length +”\r\n”;
strHttpRequest += “Host: ” + address.Host + “\r\n\r\n”;
strHttpRequest += postdata + “\r\n”;
return SendWebRequest(address.Host, strHttpRequest, address.Scheme == Uri.UriSchemeHttps);
}
Great sharing, but still I can not make it works 😦
LikeLike