using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
/************************************************************************/
/* Author:huliang
* Email:huliang@yahoo.cn
* 注意:转载请注明出处
* 摘自:http://www.cnblogs.com/cxwx/archive/2013/01/18/2865948.html
/************************************************************************/ namespace LiangHu
{
/// <summary>
/// HTTP协议头包装
/// </summary>
public class HttpHeader
{
public HttpHeader()
: this("")
{
} public HttpHeader(string url)
{
this.Url = url;
} public string Url
{
get;
set;
} public string Host
{
get;
set;
} public string Accept
{
get;
set;
} public string Referer
{
get;
set;
} public string Cookies
{
get;
set;
} public string Body
{
get;
set;
} Dictionary<string, string> m_Others = new Dictionary<string, string>(); public string this[string key]
{
get
{
return m_Others.ContainsKey(key) ? m_Others.ContainsKey(key) : null;
}
set
{
Add(key, value);
}
} public void Add(string key, string value)
{
switch (key.ToUpper())
{
case "URL":
this.Url = value;
break;
case "HOST":
this.Host = value;
break;
case "ACCEPT":
this.Accept = value;
break;
case "REFERER":
this.Referer = value;
break;
case "BODY":
this.Body = value;
break;
default:
if (!m_Others.ContainsKey(key))
{
m_Others.Add(key, value);
}
else
{
m_Others[key] = value;
}
break;
}
}
} /// <summary>
/// HTTP回应包装
/// </summary>
public class HttpResponse
{
internal HttpResponse(string header,
byte[] body)
{
this.Header = header;
this.Body = body;
} //暂未将回应HTTP协议头转换为HttpHeader类型
public string Header
{
get;
private set;
} public byte[] Body
{
get;
private set;
}
} /// <summary>
/// HttpHelper
/// </summary>
public static class HttpHelper
{
/// <summary>
/// 提交方法
/// </summary>
enum HttpMethod
{
GET,
POST
} #region HttpWebRequest & HttpWebResponse /// <summary>
/// Get方法
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="cookieContainer">Cookies存储器</param>
/// <param name="encoding">返回内容的编码格式</param>
/// <param name="others">其他需要补充的HTTP协议头</param>
/// <returns>请求结果</returns>
public static string Get(string url,
CookieContainer cookieContainer,
Encoding encoding,
Dictionary<string, string> others = null)
{
return InternalHttp(HttpMethod.GET, url, null, cookieContainer, encoding, others);
} /// <summary>
/// Post方法
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="body">Post内容</param>
/// <param name="cookieContainer">Cookies存储器</param>
/// <param name="encoding">返回内容编码</param>
/// <param name="others">其他需要补充的HTTP协议头</param>
/// <returns>请求结果</returns>
public static string Post(string url,
byte[] body,
CookieContainer cookieContainer,
Encoding encoding,
Dictionary<string, string> others = null)
{
return InternalHttp(HttpMethod.POST, url, body, cookieContainer, encoding, others);
} /// <summary>
/// Http操作
/// </summary>
/// <param name="method">请求方式</param>
/// <param name="url">请求地址</param>
/// <param name="bytes">提交的数据</param>
/// <param name="cookieContainer">Cookies存储器</param>
/// <param name="encoding">返回内容编码</param>
/// <param name="others">其他需要补充的HTTP协议头</param>
/// <returns>请求结果</returns>
static string InternalHttp(HttpMethod method,
string url,
byte[] bytes,
CookieContainer cookieContainer,
Encoding encoding,
Dictionary<string, string> others = null)
{
string result = string.Empty;
if (string.IsNullOrEmpty(url))
throw new ArgumentNullException("请求地址不能为空");
if (method == HttpMethod.POST)
{
if (bytes == null)
throw new ArgumentNullException("提交的数据不能为空");
}
if (cookieContainer == null)
throw new ArgumentNullException("Cookies存储器不能为空");
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = method.ToString();
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1;MSIE 9.0;)";
request.CookieContainer = cookieContainer;
if (method == HttpMethod.POST)
{
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = bytes.Length;
using (Stream stream = request.GetRequestStream())
{
stream.Write(bytes, 0, bytes.Length);
stream.Flush();
}
}
if (others != null)
{
foreach (KeyValuePair<string, string> pair in others)
{
request.Headers.Add(pair.Key, pair.Value);
}
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
using (StreamReader reader = new StreamReader(response.GetResponseStream(), encoding))
{
result = reader.ReadToEnd();
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return result;
} #endregion #region Socket static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
/*
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
return false;
*/
return true;
} public static HttpResponse Get(IPEndPoint endpoint,
HttpHeader header)
{
return Get(endpoint, header, null);
} public static HttpResponse Get(IPEndPoint endpoint,
HttpHeader header,
X509CertificateCollection x509certs)
{
return InternalSslSocketHttp(HttpMethod.GET, endpoint, header, x509certs);
} public static HttpResponse Post(IPEndPoint endpoint,
HttpHeader header)
{
return Post(endpoint, header, null);
} public static HttpResponse Post(IPEndPoint endpoint,
HttpHeader header,
X509CertificateCollection x509certs)
{
return InternalSslSocketHttp(HttpMethod.POST, endpoint, header, x509certs);
} static HttpResponse InternalSslSocketHttp(HttpMethod method,
IPEndPoint endpoint,
HttpHeader header,
X509CertificateCollection x509certs)
{
HttpResponse response = null;
try
{
TcpClient tcp = new TcpClient();
tcp.Connect(endpoint);
if (tcp.Connected)
{
byte[] buff = ParseHttpHeaderToBytes(method, header); //生成协议包
if (x509certs != null)
{
using (SslStream ssl = new SslStream(tcp.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null))
{
ssl.AuthenticateAsClient("SslServerName",
x509certs,
SslProtocols.Tls,
false);
if (ssl.IsAuthenticated)
{
ssl.Write(buff);
ssl.Flush();
response = ReadResponse(ssl);
}
}
}
else
{
using (NetworkStream ns = tcp.GetStream())
{
ns.Write(buff, 0, buff.Length);
ns.Flush();
response = ReadResponse(ns);
}
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return response;
} class TaskArguments
{
public TaskArguments(CancellationTokenSource cancelSource, Stream sm)
{
this.CancelSource = cancelSource;
this.Stream = sm;
}
public CancellationTokenSource CancelSource { get; private set; }
public Stream Stream { get; private set; }
} private static HttpResponse ReadResponse(Stream sm)
{
HttpResponse response = null;
CancellationTokenSource cancelSource = new CancellationTokenSource();
Task<string> myTask = Task.Factory.StartNew<string>(
new Func<object, string>(ReadHeaderProcess),
new TaskArguments(cancelSource,sm),
cancelSource.Token);
if (myTask.Wait(3 * 1000)) //尝试3秒时间读取协议头
{
string header = myTask.Result;
if (!string.IsNullOrEmpty(header))
{
if (header.StartsWith("HTTP/1.1 100"))
{
return ReadResponse(sm);
}
byte[] buff = null;
int start = header.ToUpper().IndexOf("CONTENT-LENGTH");
int content_length = -1; //fix bug
if (start > 0)
{
string temp = header.Substring(start, header.Length - start);
string[] sArry = Regex.Split(temp, "\r\n");
content_length = Convert.ToInt32(sArry[0].Split(':')[1]);
if (content_length > 0)
{
buff = new byte[content_length];
int inread = sm.Read(buff, 0, buff.Length);
while (inread < buff.Length)
{
inread += sm.Read(buff, inread, buff.Length - inread);
}
}
}
else
{
start = header.ToUpper().IndexOf("TRANSFER-ENCODING: CHUNKED");
if (start > 0)
{
buff = ChunkedReadResponse(sm);
}
else
{
buff = SpecialReadResponse(sm);//例外
}
}
response = new HttpResponse(header, buff);
}
}
else
{
cancelSource.Cancel(); //超时的话,别忘记取消任务哦
}
return response;
} static string ReadHeaderProcess(object args)
{
TaskArguments argument = args as TaskArguments;
StringBuilder bulider = new StringBuilder();
if (argument != null)
{
Stream sm = argument.Stream;
while (!argument.CancelSource.IsCancellationRequested)
{
try
{
int read = sm.ReadByte();
if (read != -1)
{
byte b = (byte)read;
bulider.Append((char)b);
string temp = bulider.ToString();
if (temp.EndsWith("\r\n\r\n"))//Http协议头尾
{
break;
}
}
else
{
break;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
break;
}
}
}
return bulider.ToString();
} class ArraySegmentList<T>
{
List<ArraySegment<T>> m_SegmentList = new List<ArraySegment<T>>();
public ArraySegmentList() { } int m_Count = 0;
public void Add(ArraySegment<T> arraySegment)
{
m_Count += arraySegment.Count;
m_SegmentList.Add(arraySegment);
} public T[] ToArray()
{
T[] array = new T[m_Count];
int index = 0;
for (int i = 0; i < m_SegmentList.Count; i++)
{
ArraySegment<T> arraySegment = m_SegmentList[i];
Array.Copy(arraySegment.Array,
0,
array,
index,
arraySegment.Count);
index += arraySegment.Count;
}
return array;
}
}
static byte[] ChunkedReadResponse(Stream sm)
{
ArraySegmentList<byte> arraySegmentList = new ArraySegmentList<byte>();
int chunked = GetChunked(sm);
while (chunked > 0)
{
byte[] buff = new byte[chunked];
try{
int inread = sm.Read(buff, 0, buff.Length);
while (inread < buff.Length)
{
inread += sm.Read(buff, inread, buff.Length - inread);
}
arraySegmentList.Add(new ArraySegment<byte>(buff));
if (sm.ReadByte() != -1)//读取段末尾的\r\n
{
sm.ReadByte();
}
}catch(Exception){
break;
}
chunked = GetChunked(sm);
}
return arraySegmentList.ToArray();
} static int GetChunked(Stream sm)
{
int chunked = 0;
StringBuilder bulider = new StringBuilder();
while (true)
{
try
{
int read = sm.ReadByte();
if (read != -1)
{
byte b = (byte)read;
bulider.Append((char)b);
string temp = bulider.ToString();
if (temp.EndsWith("\r\n"))
{
chunked = Convert.ToInt32(temp.Trim(), 16);
break;
}
}
else
{
break;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
break;
}
}
return chunked;
} /*
* 注意:该方法仅供测试,实际使用时请根据需要定制
*/
static byte[] SpecialReadResponse(Stream sm)
{
ArrayList array = new ArrayList();
StringBuilder bulider = new StringBuilder();
int length = 0;
DateTime now = DateTime.Now;
while (true)
{
byte[] buff = new byte[1024 * 10];
int len = sm.Read(buff, 0, buff.Length);
if (len > 0)
{
length += len;
byte[] reads = new byte[len];
Array.Copy(buff, 0, reads, 0, len);
array.Add(reads);
bulider.Append(Encoding.Default.GetString(reads));
}
string temp = bulider.ToString();
if (temp.ToUpper().Contains("</HTML>"))
{
break;
}
if (DateTime.Now.Subtract(now).TotalSeconds >= 30)
{
break;//超时30秒则跳出
}
}
byte[] bytes = new byte[length];
int index = 0;
for (int i = 0; i < array.Count; i++)
{
byte[] temp = (byte[])array[i];
Array.Copy(temp, 0, bytes,
index, temp.Length);
index += temp.Length;
}
return bytes;
} #endregion #region Helper /// <summary>
/// 将HTTP协议头转换为Bytes数据
/// </summary>
/// <param name="method">HTTP方法</param>
/// <param name="header">HTTP协议头</param>
/// <returns>Bytes数据</returns>
static byte[] ParseHttpHeaderToBytes(HttpMethod method, HttpHeader header)
{
StringBuilder bulider = new StringBuilder();
if (method.Equals(HttpMethod.POST))
{
bulider.AppendLine(string.Format("POST {0} HTTP/1.1",
header.Url));
bulider.AppendLine("Content-Type: application/x-www-form-urlencoded");
}
else
{
bulider.AppendLine(string.Format("GET {0} HTTP/1.1",
header.Url));
}
if (!string.IsNullOrEmpty(header.Host))
bulider.AppendLine(string.Format("Host: {0}",
header.Host));
bulider.AppendLine("User-Agent: Mozilla/5.0 (Windows NT 6.1; IE 9.0)");
if (!string.IsNullOrEmpty(header.Referer))
bulider.AppendLine(string.Format("Referer: {0}",
header.Referer));
bulider.AppendLine("Connection: keep-alive");
if (!string.IsNullOrEmpty(header.Accept))
{
bulider.AppendLine(string.Format("Accept: {0}",
header.Accept));
}
else
{
bulider.AppendLine("Accept: */*");
}
if (!string.IsNullOrEmpty(header.Cookies))
bulider.AppendLine(string.Format("Cookie: {0}",
header.Cookies));
if (method.Equals(HttpMethod.POST))
{
bulider.AppendLine(string.Format("Content-Length: {0}\r\n",
Encoding.Default.GetBytes(header.Body).Length));
bulider.Append(header.Body);
}
else
{
bulider.Append("\r\n");
}
return Encoding.Default.GetBytes(bulider.ToString());
} /// <summary>
/// 从Url中提取Host信息
/// </summary>
/// <param name="url">Url</param>
/// <returns>Host信息</returns>
public static string GetHost(string url)
{
string host = string.Empty;
try
{
Uri uri = new Uri(url);
host = uri.Host;
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return host;
} /// <summary>
/// 通过Host获取IP地址
/// </summary>
/// <param name="host">Host</param>
/// <returns>IP地址</returns>
public static IPAddress GetAddress(string host)
{
IPAddress address = IPAddress.Any;
try
{
IPAddress[] alladdress = Dns.GetHostAddresses(host);
if (alladdress.Length > 0)
{
address = alladdress[0];
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return address;
} /// <summary>
/// 从HTTP返回头协议中取Set-Cookie信息(即Cookies)
/// </summary>
/// <param name="responseHeader">HTTP返回头协议</param>
/// <returns>Cookies</returns>
public static string GetCookies(string responseHeader)
{
StringBuilder cookies = new StringBuilder();
using (StringReader reader = new StringReader(responseHeader))
{
string strLine = reader.ReadLine();
while (strLine != null)
{
if (strLine.StartsWith("Set-Cookie:"))
{
string temp = strLine.Remove(0, 12);
if (!temp.EndsWith(";"))
{
temp = temp + ";";
}
cookies.Append(temp);
}
strLine = reader.ReadLine();
}
}
return cookies.ToString();
} /// <summary>
/// 从HTTP返回头协议中去Location地址(一般出现在301跳转)
/// </summary>
/// <param name="responseHeader">HTTP返回头协议</param>
/// <returns>Location地址</returns>
public static string GetLocation(string responseHeader)
{
string result = string.Empty;
using (StringReader reader = new StringReader(responseHeader))
{
string strLine = reader.ReadLine();
while (strLine != null)
{
if (strLine.StartsWith("Location:"))
{
result = strLine.Remove(0, 10);
}
strLine = reader.ReadLine();
}
}
return result;
} #endregion
}
}

Sokcet方式请求HTTP/HTTPS的封装类HttpHelper的更多相关文章

  1. JAVA Socket 实现HTTP与HTTPS客户端发送POST与GET方式请求

    JAVA Socket 实现HTTP与HTTPS客户端发送POST与GET方式请求 哇,一看标题怎么这么长啊,其实意思很简单,哥讨厌用HTTP Client做POST与GET提交 觉得那个毕竟是别人写 ...

  2. PHP:CURL分别以GET、POST方式请求HTTPS协议接口api

    1.curl以GET方式请求https协议接口 //注意:这里的$url已经包含参数了,不带参数你自己处理哦GET很简单 function curl_get_https($url){ $curl = ...

  3. PHP函数CURL分别以GET、POST方式请求HTTPS协议接口api

    1.curl以GET方式请求https协议接口 function curl_get_https($url){ $curl = curl_init(); // 启动一个CURL会话 curl_setop ...

  4. PHP:CURL分别以GET、POST方式请求HTTPS协议接口api【转】

    1.curl以GET方式请求https协议接口 //注意:这里的$url已经包含参数了,不带参数你自己处理哦GET很简单 function curl_get_https($url){ $curl = ...

  5. asp.net core 自定义认证方式--请求头认证

    asp.net core 自定义认证方式--请求头认证 Intro 最近开始真正的实践了一些网关的东西,最近写几篇文章分享一下我的实践以及遇到的问题. 本文主要介绍网关后面的服务如何进行认证. 解决思 ...

  6. 使用CURL实现GET和POST方式请求

    /** 使用curl方式实现get或post请求@param $url 请求的url地址@param $data 发送的post数据 如果为空则为get方式请求return 请求后获取到的数据 */f ...

  7. http请求在https中使用

    问题原因:HTTPS页面里动态的引入HTTP资源,比如引入一个js文件,会被直接block掉的.在HTTPS页面里通过AJAX的方式请求HTTP资源,也会被直接block掉的. 解决方案: <m ...

  8. php使用CURL实现GET和POST方式请求

    CURL请求,支持GET和POST两种方式,默认为GET方式,如果传第二个参数则为POST方式请求,设置了超时时间,避免程序卡死. /** 使用curl方式实现get或post请求 @param $u ...

  9. Ajax-(get/post/jQuery方式请求)

    < !DOCTYPE html > < html xmlns = "http://www.w3.org/1999/xhtml" > < head &g ...

随机推荐

  1. Android系统的五种数据存储形式(一)

    Android系统有五种数据存储形式,分别是文件存储.SP存储.数据库存储.contentprovider 内容提供者.网络存储.其中,前四个是本地存储.存储的类型包括简单文本.窗口状态存储.音频视频 ...

  2. Android项目实战(二十七):数据交互(信息编辑)填写总结

    前言: 项目中必定用到的数据填写需求.比如修改用户名的文字编辑对话框,修改生日的日期选择对话框等等.现总结一下,方便以后使用. 注: 先写实现过程,想要学习的同学可以看看,不需要的同学可以直接拉到最下 ...

  3. 【原】设置iOS项目BuildVersion自动增加

    一.概念阐述:Build与Version的区别 在iOS中有两种“版本号”,也就是所谓的version号与build号,如下图所示: 我们用最简洁的语言来区分这两个版本号的区别以及用途如下: Vers ...

  4. Request 和 Response 原理

    * Request 和 Response 原理:     * request对象和response对象由服务器创建,我们只需要在service方法中使用这两个对象即可        * 继承体系结构: ...

  5. CocoaPods安装及使用详情

    CocoaPods是什么? 当你开发iOS应用时,会经常使用到很多第三方开源类库,比如JSONKit,SDWebImage等等.可能某个类库又用到其他类库,所以要使用它,必须得另外下载其他类库,而其他 ...

  6. web.xml中监听器配置

    <!-- 监听器的配置:监听器配置完以后,应用系统在启动的时候就会开启这些监听器. 监听器的理解:监听器好比一个卫兵,卫兵一直站在那里等待长官的命令,当卫兵收到长官的命令以后,立即执行 之前已经 ...

  7. ionic入门01

    总述 ionic是一个强大的混合式/hybrid HTML5移动开发框架,特点是使用标准的HTML.CSS和JavaScript,开发跨平台的应用. 接下来,敝人会从0到1采用ionic构建一个简单的 ...

  8. 还来一篇说下json_value 以及 json_query 的应用 (3)

    上一篇说了一下openjson 的一些使用方法,这次再说一下在2016里面的查询取值,当然就是 json_query 和 json_value 这2兄弟了 首先 ) = '{"a" ...

  9. x01.Weiqi.10: 死活问题

    估计得不错,点目后,仅一个方法:UpdateMeshes5() 就完美解决了梅花六.刀把五.斗笠四.盘角曲四等死活问题.先来看看效果图: 其代码如下: void UpdateMeshes5(bool ...

  10. markdown简要说明源码

    ##markdown ###什么是markdown:    Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式.  Markdown具有 ...