遇到Https网站,c# http请求的时候,总是报SSL连接错误。后来经搜索,发现有解决方案:

.net 2.0  需要引入一个第三方组件:BouncyCastle.dll,这是我写的一个例子:

        public static string RequestWebServerByTCP(Uri uri, string method, NameValueCollection parameter, string cookie, Encoding encoding)
{
try
{
StringBuilder RequestHeaders = new StringBuilder(); RequestHeaders.Append(method + " " + uri.PathAndQuery + " HTTP/1.1\r\n"); method = method.ToUpper(); if (method == POSTMETHOD)
RequestHeaders.Append("Content-Type:application/x-www-form-urlencoded\r\n");
RequestHeaders.Append("User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11\r\n");
RequestHeaders.Append("Cookie:" + cookie + "\r\n");
RequestHeaders.Append("Accept:*/*\r\n");
RequestHeaders.Append("Host:" + uri.Host + "\r\n"); byte[] postdata = null;
StringBuilder sb = new StringBuilder(); if (method == GETMETHOD)
{
uri = GetMethodQueryString(uri, parameter, encoding);
}
else if (method == POSTMETHOD)
{
if (parameter != null)
{
foreach (string key in parameter)
{
sb.Append(string.Format(FORMATSTR1, System.Web.HttpUtility.UrlEncode(key, encoding), System.Web.HttpUtility.UrlEncode(parameter[key], encoding)));
}
}
if (sb.Length != )
{
sb = sb.Remove(sb.Length - , );
}
postdata = encoding.GetBytes(sb.ToString()); RequestHeaders.Append("Content-Length:" + postdata.Length + "\r\n");
} RequestHeaders.Append("Connection:close\r\n\r\n");
byte[] req = Encoding.UTF8.GetBytes(RequestHeaders.ToString() + sb.ToString()); int port = ; MyTlsClient client = new MyTlsClient();
var protocol = OpenTlsConnection(uri.Host, port, client); Stream tlsStream = protocol.Stream;
tlsStream.Write(req, , req.Length);
tlsStream.Flush(); StreamReader reader = new StreamReader(tlsStream); String line;
StringBuilder html = new StringBuilder(); string firstLine = ""; int i = ; while ((line = reader.ReadLine()) != null)
{
if (i == )
{
firstLine = line;
i++;
} html.AppendLine(line); if (line.Contains("</html>"))
{
break;
}
}
protocol.Close(); string httpstatusCode = ""; string[] httpstatus = firstLine.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
if (httpstatus.Length > )
{
httpstatusCode = httpstatus[];
}
else
{
//请求无效
httpstatusCode = "";
}
return html.ToString(); }
catch
{
return "";
} }

  请求到的html,为什么需要一行一行读呢?我在调试的时候发现有个bug,如果一次性读取的时候,它停不下来,最终报错,所以我做了一个读到html末尾的判断。

继承了提供的默认类:

  class MyTlsClient : DefaultTlsClient
{
public override TlsAuthentication GetAuthentication()
{
return new MyTlsAuthentication();
}
} // Need class to handle certificate auth
class MyTlsAuthentication : TlsAuthentication
{
public TlsCredentials GetClientCredentials(CertificateRequest certificateRequest)
{
// return client certificate
return null;
} public void NotifyServerCertificate(Certificate serverCertificate)
{
// validate server certificate
}
}
       internal static TlsClientProtocol OpenTlsConnection(string hostname, int port, TlsClient client)
{
TcpClient tcp = new TcpClient(hostname, port); TlsClientProtocol protocol = new TlsClientProtocol(tcp.GetStream(), secureRandom);
protocol.Connect(client);
return protocol;
}

拼接url参数的方法:

      private static Uri GetMethodQueryString(Uri uri, NameValueCollection parameter, Encoding encoding)
{
List<KeyValuePair<string, string>> parameter1 = new List<KeyValuePair<string, string>>();
foreach (string key in parameter)
{
parameter1.Add(new KeyValuePair<string, string>(key, parameter[key]));
}
return GetMethodQueryString(uri, parameter1, encoding);
} private static Uri GetMethodQueryString(Uri uri, List<KeyValuePair<string, string>> parameter, Encoding encoding)
{
string format = string.Empty;
UriBuilder uribuilfer = new UriBuilder(uri); string QueryString = string.Empty;
if (string.IsNullOrEmpty(uribuilfer.Query))
{
format = FORMATSTR1;
}
else
{
format = FORMATSTR2;
}
QueryString = uribuilfer.Query;
if (parameter != null)
{
foreach (KeyValuePair<string, string> item in parameter)
{
QueryString += string.Format(format, System.Web.HttpUtility.UrlEncode(item.Key, encoding), System.Web.HttpUtility.UrlEncode(item.Value, encoding));
}
}
QueryString = QueryString.TrimEnd(new char[] { '&' });
QueryString = QueryString.TrimStart(new char[] { '?' });
uribuilfer.Query = QueryString;
uri = uribuilfer.Uri;
return uri;
}

  注意:List<KeyValuePair<string, string>>NameValueCollection类型的参数有什么区别呢?它们都包含相同的key,只不过存储的时候,NameValueCollection会把含有相同Key的值用逗号隔开,存在一起。这样请求有可能会失败,拿不到数据。本人因此问题,折腾了很久,用python实现了请求,后来在.net core中实现了一遍,最后终于低下了高傲的头颅,才看到传参时候,有点问题。

.net  4.0中,只需要添加一句话:ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

       .net 4.5中,什么都不用管。

2.0中连TCP都用上了,不过我们看到了http请求的本质,把一段具有格式的请求头+请求数据转为二进制发送到主机的某个端口,返回流,通过读取流,就可以拿到结果。

说到这,我们来看看Request消息格式:

GET https://www.baidu.com/ HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Host: www.baidu.com
Cookie: BAIDUID=C1EFC3A3466AAAEBE74C6F6E7F413FA8:FG=1; BIDUPSID=C1EFC3A3466AAAEBE74C6F6E7F413FA8; PSTM=1525339270; BD_LAST_QID=12260391193367555241

1、请求行,包含请求的方法,url,http协议版本

2、请求头,接收的格式,浏览器代理,cookie等等

3、空行

4、请求体,传递数据

Response格式:

HTTP/1.1 200 OK
Bdpagetype: 1
Bdqid: 0x9a1ff959000016d0
Cache-Control: private
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Cxy_all: baidu+77e5655ffd82ce31adf5edff251fc585
Date: Thu, 03 May 2018 09:21:10 GMT
Expires: Thu, 03 May 2018 09:21:03 GMT
Server: BWS/1.1
Set-Cookie: BDSVRTM=0; path=/
Set-Cookie: BD_HOME=0; path=/
Set-Cookie: H_PS_PSSID=1428_21080_20719; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=172800
Vary: Accept-Encoding
X-Powered-By: HPHP
X-Ua-Compatible: IE=Edge,chrome=1
Transfer-Encoding: chunked html

1、状态行

2、消息报头,content-type,Date,Set-Cookie

3、空行

4、正文

c# https请求的更多相关文章

  1. Http、Https请求工具类

    最近在做微信开发,使用http调用第三方服务API,有些是需要https协议,通过资料和自己编码,写了个支持http和https的工具类,经验证可用,现贴出来保留,也供需要的人使用(有不足的地方,也请 ...

  2. charles4抓https请求的注意事项

    最近升级charles4.0后发现抓不了https请求了,但很奇怪ssl证书一样,记得以前用3.0就可以,今天仔细研究了一下,发现4.0的ssl代理设置中有一段说明(可能3.0也有但没注意): 直接上 ...

  3. 使用curl进行https请求

    简单示例: /** * @param $url * @return array * 进行https请求,并且遇到location进行跳转 */ function https($url){ $resul ...

  4. 在C#用HttpWebRequest中发送GET/HTTP/HTTPS请求

    通用辅助类  下面是我编写的一个辅助类,在这个类中采用了HttpWebRequest中发送GET/HTTP/HTTPS请求,因为有的时候需 要获取认证信息(如Cookie),所以返回的是HttpWeb ...

  5. 【转载】JMeter学习(三十六)发送HTTPS请求

    Jmeter一般来说是压力测试的利器,最近想尝试jmeter和BeanShell进行接口测试.由于在云阅读接口测试的过程中需要进行登录操作,而登录请求是HTTPS协议.这就需要对jmeter进行设置. ...

  6. 如何使用查尔斯代理抓取https请求

    首先 查尔斯代理是一个很不错的抓包工具 有适合各种系统的版本 最近http的请求几乎铺天盖地的已经变为了https了  其中的好处有很多  更加安全(http://www.cnblogs.com/lo ...

  7. C# HttpWebRequest GET HTTP HTTPS 请求

    下面是我编写的一个辅助类,在这个类中采用了HttpWebRequest中发送GET/HTTP/HTTPS请求,因为有的时候需要获取认证信息(如Cookie),所以返回的是HttpWebResponse ...

  8. 微信https请求工具类

    工作中用到的微信https请求工具类. package com.gxgrh.wechat.tools; import com.gxgrh.wechat.wechatapi.service.System ...

  9. python——请求服务器(http请求和https请求)

    一.http请求 1.http请求方式:get和post get一般用于获取/查询资源信息,在浏览器中直接输入url+请求参数点击enter之后连接成功服务器就能获取到的内容,post请求一般用于更新 ...

  10. java 实现https请求

    java 实现https请求 JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易地编程实现对HTTPS站点的访问.但是,如果该站点的证书未经权威机构的验证,JSSE将拒绝信任该证书从 ...

随机推荐

  1. antlr v4 使用指南连载2——准备环境

    antlr v4 开发环境         从上一篇文章的例子中可以知道,antlr有一套自己的语法来声明目标语言的语法,因此它本身就需要编译或者使用antlr提供的api来读取这些语法规则,并使之可 ...

  2. Dynamics CRM Import Solution Attribute Display Name description is null or empty

    在做解决方案导入的时候遇到错误,下载错误xml信息后查询报错如下:"Attribute Display Name description is null or empty",字面意 ...

  3. Java基础---Java---网络编程---TCP、UDP、UDP-键盘录入方式数据、Socket、TCP复制文件、UDP-聊天

    网络编程 网络模型 *OSI参考模型 *Tcp/IP参考模型 网络通读要素 *IP地址 *端口号 *传输协议 1.找到对方Ip 2.数据要发送到对方指定的的应用程序上,为了标识这些应用程序,所经给这些 ...

  4. UNIX网络编程——sockatmark函数

    每当收到一个带外数据时,就有一个与之关联的带外标记.这是发送进程发送带外字节时该字节在发送端普通数据流中的位置.在从套接字读入期间,接收进程通过调用sockatmark函数确定是否处于带外标记. #i ...

  5. tomcat请求路由映射核心组件Mapper

    Mapper组件的核心功能是提供请求路径的路由映射,根据某个请求路径通过计算得到相应的Servlet(Wrapper).这节看下Mapper的实现细节,包括Host容器.Context容器.Wrapp ...

  6. 【java虚拟机系列】java中类与对象的加载顺序

    首先了解一下Java虚拟机初始化的原理. JVM通过加装.连接和初始化一个Java类型,使该类型可以被正在运行的Java程序所使用.类型的生命周期如下图所示: 装载和连接必须在初始化之前就要完成. 类 ...

  7. PHP解决中文乱码问题

    初学PHP,在汉字页面间传输和转换的时候,遇到了中文乱码问题. 究其原因乱码无外乎以下几种情况: 1.html页本身的乱码问题, 解决方法:纯html页使用<meta http-equiv=&q ...

  8. iOS中 FMDB第三方SQLite数据库 UI_20

    1.什么是FMDB? FMDB是iOS平台下SQLite数据库,只不过它是OC方式封装了C语言的SQLite语句,使用起来更加面向对象 2.FMDB的优点:1.使用起来更加面向对象; 2.对比苹果自带 ...

  9. Cell自适应高度及自定义cell混合使…

    第一部分:UItableViewCellAdaptionForHeight : cell的自适应高度 第二部分:CustomTableViewCell:自定义cell的混合使用(以简单通讯录为例) = ...

  10. UNIX环境高级编程——文件和目录

    一.获取文件/目录的属性信息 int stat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf); in ...