极光推送C#版本在XP系统下提示“基础连接已经关闭: 接收时发生意外错误”的解决方案



极光推送服务器用的SSL协议版本是TLS1.2,而TLS 1.2 必须要 .NET 4.5或以上版本,然而XP系统是不支持 .NET 4.5或以上版本的。解决方法就是http请求弃用.NET自带的WebRequest,自己使用TCP写HTTPS请求。


两篇参考文章:
.net2.0用TLS1.2+TCP Stream访问https网站
http://blog.csdn.net/atceedsun/article/details/50443657


C# 使用TCPCLIENT模拟HTTP请求的使用
http://www.cnblogs.com/orange-huihui/articles/3266224.html


我的具体做法:


1.cn.jpush.api引用第一篇参考文章里提到的第三方库BouncyCastle.dll;


2.cn.jpush.api的common文件夹下增加一个自定义http请求类,代码如下:


using Org.BouncyCastle.Crypto.Tls;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;


namespace cn.jpush.api.common
{
    // Need class with TlsClient in inheritance chain  
    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  
        }
    }


    public class MyHttp
    {
        public static Response HTTP(string _type, string _url, String _auth = "", string _postdata = "", string _cookie = "")
        {
            Encoding _responseEncode = Encoding.UTF8;


            int port = 80;


            try
            {
                if (_url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    port = 443;
                }
                else
                { }


                Uri URI = new Uri(_url);


                TcpClient tcpClient = new TcpClient(URI.Host, port);
                TlsClientProtocol protocol = new TlsClientProtocol(tcpClient.GetStream(), new Org.BouncyCastle.Security.SecureRandom());
                MyTlsClient client = new MyTlsClient();
                protocol.Connect(client);


                //utf8编码
                byte[] bs = UTF8Encoding.UTF8.GetBytes(_postdata);


                StringBuilder RequestHeaders = new StringBuilder();


                RequestHeaders.Append(_type + " " + URI.PathAndQuery + " HTTP/1.1\r\n");
                //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");
                RequestHeaders.Append("Content-Length: " + bs.Length + "\r\n");
                //RequestHeaders.Append("Connection: close\r\n");
                if (!String.IsNullOrEmpty(_auth))
                {
                    RequestHeaders.Append("Authorization: " + "Basic " + _auth + "\r\n");
                }
                RequestHeaders.Append("\r\n");
                byte[] request = Encoding.UTF8.GetBytes(RequestHeaders.ToString() + _postdata);


                //发送http请求  
                protocol.Stream.Write(request, 0, request.Length);
                protocol.Stream.Flush();


                //读取返回内容  
                MemoryStream ms = new MemoryStream();


                byte[] buffer = new byte[1024000];
                int actual = 0;
                //先保存到内存流MemoryStream中
                try
                {
                    if ((actual = protocol.Stream.Read(buffer, 0, 1024000)) > 0)
                    {
                        ms.Write(buffer, 0, actual);
                    }
                }
                catch { }
                ms.Position = 0;
                byte[] bImageBytes = ms.ToArray();
                string result = Encoding.UTF8.GetString(bImageBytes);


                //Console.WriteLine(result);


                int headerIndex = result.IndexOf("\r\n\r\n");
                string[] headerStr = result.Substring(0, headerIndex).Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                Dictionary<string, string> responseHeader = new Dictionary<string, string>();
                for (int i = 0; i < headerStr.Length; i++)
                {
                    string[] temp = headerStr[i].Split(new string[] { ": " }, StringSplitOptions.RemoveEmptyEntries);
                    if (temp.Length == 2)
                    {
                        if (responseHeader.ContainsKey(temp[0]))
                        {
                            responseHeader[temp[0]] = temp[1];
                        }
                        else
                        {
                            responseHeader.Add(temp[0], temp[1]);
                        }
                    }
                }
                Response response = new Response();
                response.HTTPResponseHeader = responseHeader;
                string[] httpstatus = headerStr[0].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                if (httpstatus.Length > 2)
                {
                    response.HTTPStatusCode = httpstatus[1];
                }
                else
                {
                    response.HTTPStatusCode = "400";
                }
                response.HTTPResponseText = _responseEncode.GetString(Encoding.UTF8.GetBytes(result.Substring(headerIndex + 4)));
                return response;
            }
            catch
            {
                return null;
            }
        }
    }


    public class Response
    {


        string hTTPStatusCode;
        ///   
        /// http状态代码  
        ///   
        public string HTTPStatusCode
        {
            get { return hTTPStatusCode; }
            set { hTTPStatusCode = value; }
        }




        Dictionary<string, string> hTTPResponseHeader;
        ///   
        /// Response的header  
        ///   
        public Dictionary<string, string> HTTPResponseHeader
        {
            get { return hTTPResponseHeader; }
            set { hTTPResponseHeader = value; }
        }


        string hTTPResponseText;
        ///   
        /// html代码  
        ///   
        public string HTTPResponseText
        {
            get { return hTTPResponseText; }
            set { hTTPResponseText = value; }
        }




    }
}


3.将cn.jpush.api的common文件夹下的BaseHttpClient.cs里的


public ResponseWrapper sendRequest1(String method, String url, String auth,String reqParams)


方法替换为:


public ResponseWrapper sendRequest(String method, String url, String auth, String reqParams)
        {
            //结果wrap
            ResponseWrapper result = new ResponseWrapper();


            try
            {
                //response
                //调用自定义http请求,因为极光推送服务器使用的SSL-TLS1.2版本,必须要.net4.5以上框架才支持,所以只能使用自定义http请求并调用第三方ssl框架实现
                Response response = MyHttp.HTTP(method, url, auth, reqParams);


                //http status code
                HttpStatusCode statusCode = (HttpStatusCode)Convert.ToInt32(response.HTTPStatusCode);
                result.responseCode = statusCode;
                if (Equals(statusCode, HttpStatusCode.OK))
                {
                    Regex regpatton = new Regex(@"{(.*)}");
                    MatchCollection jsons = regpatton.Matches(response.HTTPResponseText);


                    if (jsons.Count > 0)
                    {
                        result.responseContent = jsons[0].ToString(); 
                    }


                    String limitQuota = response.HTTPResponseHeader[RATE_LIMIT_QUOTA];
                    String limitRemaining = response.HTTPResponseHeader[RATE_LIMIT_Remaining];
                    String limitReset = response.HTTPResponseHeader[RATE_LIMIT_Reset];
                    result.setRateLimit(limitQuota, limitRemaining, limitReset);
                    Console.WriteLine("Succeed to get response - 200 OK" + " " + DateTime.Now);
                    Console.WriteLine("Response Content - {0}", result.responseContent + " " + DateTime.Now);
                }
            }
            catch { }


            return result;
        }




4.提示有引用问题的,使用修复功能增加相应的引用就成了。


至此,大功告成! 


PS:写的比较清楚了,就没有上传完整示例,实在有需要可以向402143909@qq.com索取。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值