When encountering HTTPS websites, C # HTTP requests are always reported as SSL connection errors. Later, after searching, we found a solution:
. NET 2.0 requires the introduction of a third-party component:BouncyCastle.dll, This is an example I wrote:
Public Static stringRequestwebserverbytcp (Uri Uri,stringmethod, NameValueCollection parameter,stringcookies, Encoding Encoding) { Try{StringBuilder requestheaders=NewStringBuilder (); 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 ("Cookies:"+ Cookies +"\ r \ n"); Requestheaders.append ("accept:*/*\r\n"); Requestheaders.append ("Host:"+ URI. Host +"\ r \ n"); byte[] PostData =NULL; StringBuilder SB=NewStringBuilder (); if(Method = =GetMethod) {URI=getmethodquerystring (URI, parameter, encoding); } Else if(Method = =Postmethod) { if(Parameter! =NULL) { foreach(stringKeyinchparameter) {sb. Append (string. Format (FORMATSTR1, System.Web.HttpUtility.UrlEncode (key, encoding), System.Web.HttpUtility.UrlEncode (parameter[ Key], encoding)); } } if(sb.) Length! =0) {SB= sb. Remove (sb.) Length-1,1); } 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 ()); intPort =443; Mytlsclient Client=Newmytlsclient (); varprotocol =opentlsconnection (URI. Host, port, client); Stream Tlsstream=protocol. Stream; Tlsstream.write (req,0, req. Length); Tlsstream.flush (); StreamReader Reader=NewStreamReader (Tlsstream); String Line; StringBuilder HTML=NewStringBuilder (); stringFirstline =""; inti =0; while(line = reader.) ReadLine ())! =NULL) { if(i = =0) {Firstline=Line ; I++; } HTML. Appendline (line); if(line. Contains ("")) { Break; }} protocol. Close (); stringHttpStatusCode =""; string[] Httpstatus = Firstline.split (New string[] {" "}, Stringsplitoptions.removeemptyentries); if(Httpstatus. Length >2) {HttpStatusCode= httpstatus[1]; } Else { //Invalid requestHttpStatusCode =" -"; } returnHTML. ToString (); } Catch { return ""; } }
The requested HTML, why do you need a line to read it? I found a bug when debugging, if the one-time read, it can't stop, the final error, so I made a read to the end of the HTML judgment.
Inherited the provided default class:
classmytlsclient:defaulttlsclient { Public Overridetlsauthentication getauthentication () {return Newmytlsauthentication (); } } //need class to handle certificate auth classmytlsauthentication:tlsauthentication { Publictlscredentials getclientcredentials (certificaterequest certificaterequest) {//return client certificate return NULL; } Public voidnotifyservercertificate (Certificate servercertificate) {//Validate server Certificate } }
Internal Static Tlsclientprotocol opentlsconnection (stringint port, tlsclient client) { new TcpClient (hostname, port); New Tlsclientprotocol (TCP. GetStream (), securerandom); Protocol. Connect (client); return protocol; }
Methods for stitching URL parameters:
Private StaticUri getmethodquerystring (URI uri, namevaluecollection parameter, Encoding Encoding) {List<KeyValuePair<string,string>> Parameter1 =Newlist<keyvaluepair<string,string>>(); foreach(stringKeyinchparameter) {Parameter1. ADD (Newkeyvaluepair<string,string>(Key, Parameter[key])); } returngetmethodquerystring (URI, Parameter1, encoding); } Private StaticUri getmethodquerystring (Uri Uri, list<keyvaluepair<string,string>>parameter, Encoding Encoding) { stringFormat =string. Empty; UriBuilder Uribuilfer=NewUriBuilder (URI); stringQueryString =string. Empty; if(string. IsNullOrEmpty (Uribuilfer. Query)) {format=FORMATSTR1; } Else{format=FORMATSTR2; } QueryString=Uribuilfer. Query; if(Parameter! =NULL) { foreach(keyvaluepair<string,string> Iteminchparameter) {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; returnURI; }
Note: What is the difference betweenlist<keyvaluepair<string, string>>, and namevaluecollection types of parameters? They all contain the same key, but when stored, NameValueCollection separates the values that contain the same key with commas and exists together. This can cause the request to fail and not get the data. I therefore the problem, tossing for a long time, with Python implementation of the request, and later in. NET core realized again, finally lowered the arrogant head, only to see the time of the transfer, a bit of a problem.
In. NET 4.0, you only need to add a sentence:Servicepointmanager.securityprotocol = (securityprotocoltype) 3072;
in. NET 4.5, nothing is in the pipeline.
2.0 even TCP is used, but we see the nature of the HTTP request, a piece of the format of the request header + Request data into the binary sent to a host port, return stream, by reading the stream, you can get the results.
Speaking of which, let's take a look at the request message format:
GET https://www.baidu.com/HTTP/1.1Accept:text/html, Application/xhtml+xml, */*accept-language:zh-cnuser-agent: mozilla/5.0 (Windows NT 6.1; WOW64; trident/7.0; rv:11.0) like Geckoaccept-encoding:gzip, deflateconnection:keep-alivehost:www.baidu.comcookie:baiduid= c1efc3a3466aaaebe74c6f6e7f413fa8:fg=1; BIDUPSID=C1EFC3A3466AAAEBE74C6F6E7F413FA8; pstm=1525339270; bd_last_qid=12260391193367555241
1, request line, contains the method of the request, Url,http protocol version
2. Request header, received format, browser agent, cookie, etc.
3, empty line
4, the request body, transmits the data
Response Format:
http/1.1 okbdpagetype:1bdqid:0x9a1ff959000016d0cache-control:privateconnection:keep-alivecontent-encoding: gzipcontent-type:text/html; Charset=utf-8cxy_all:baidu+77e5655ffd82ce31adf5edff251fc585date:thu, 2018 09:21:10 Gmtexpires:thu, 2018 0 9:21:03 gmtserver:bws/1.1set-cookie:bdsvrtm=0; path=/set-cookie:bd_home=0; path=/set-cookie:h_ps_pssid=1428_21080_20719; path=/; Domain=.baidu.comstrict-transport-security:max-age=172800vary:accept-encodingx-powered-by:hphpx-ua-compatible: Ie=edge,chrome=1transfer-encoding:chunked
Html
1, status line
2, message header, Content-type,date,set-cookie
3, empty line
4. Text
C # HTTPS requests