你的位置:首页 > ASP.net教程

[ASP.net教程]HTTP在.NET中的一些应用和解析


     谈到HTTP协议(超文本传输协议),HTTP协议是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式,HTTP1.1版本中给出一种持续连接的机制,绝大多数的Web开发,都是构建在HTTP协议之上的Web应用。

    HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。HTTP协议的主要特点可概括为:1.支持客户/服务器模式。2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。3.灵活:HTTP允许传输任意类型的数据对象。4.无连接:无连接的含义是限制每次连接只处理一个请求。5.无状态:HTTP协议是无状态协议。

    在.NET框架里面对HTTP协议的处理主要采用WebRequest对象,在我们的.NET项目中如果需要生成HTTP请求或者处理HTTP请求,会运用HttpWebRequest和HttpWebResponse对象。在实际项目的开发中,有一些需求需要同地方平台进行数据交互,例如我们经常使用的微信,支付宝,QQ等等平台,这就需要我们在自己的项目中生成对应的HTTP请求和处理相关HTTP请求信息。

    如何在我们的系统中后台生成对应的HTTP请求,这个事情就需要对HTTP协议做一个简单的了解:

    HTTP请求由三部分组成,分别是:请求行、消息报头、请求正文。HTTP响应也是由三个部分组成,分别是:状态行、消息报头、响应正文。HTTP消息由客户端到服务器的请求和服务器到客户端的响应组成。请求消息和响应消息都是由开始行(对于请求消息,开始行就是请求行,对于响应消息,开始行就是状态行),消息报头(可选),空行(只有CRLF的行),消息正文(可选)组成。

 

   现在提供一个较为通用的处理HTTP请求的代码,此部分主要是生成同步HTTP请求。

   在谈到.NET的同步中,需要介绍一下同步和异步的相关内容:

   同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到返回的值或消息后才往下执行其他的命令。  

   异步,执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。 

  

     (以上的图都是从别处截的,感谢提供资料的博主们。)

    现在直接给出相关代码:

   

     /// <summary>     /// 访问次数字典    /// </summary>    private readonly ConcurrentDictionary<string, int> _urlTryList = new ConcurrentDictionary<string, int>();

    /// <summary>    /// Post数据    /// </summary>    public String PostData { set; private get; }

    /// <summary>    /// 同步请求    /// </summary>    /// <param name="url">请求地址</param>    /// <param name="tryTimes">错误重试次数</param>    public string SyncRequest(string url, int tryTimes = 3)    {      if (string.IsNullOrEmpty(url))      {        throw new ArgumentNullException(url);      }      Trace.TraceInformation(string.Concat("开始同步请求:", url));      _urlTryList.TryAdd(url, tryTimes);      //创建并定义HTTP请求相关信息      var request = WebRequest.Create(url) as HttpWebRequest;      if (request == null) return string.Empty;      request.Headers.Add("Accept-Encoding", "gzip,deflate,sdch");      request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.8");      request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.None;      request.Credentials = CredentialCache.DefaultNetworkCredentials;      request.UseDefaultCredentials = false;      request.KeepAlive = false;      request.PreAuthenticate = false;      request.ProtocolVersion = HttpVersion.Version10;      request.UserAgent =        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36";      request.Accept = "text/html,application/xhtml+";      request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);      request.Timeout = 1000 * 60 * 3;      request.CookieContainer = CookieContainer;      request.AllowAutoRedirect = true;      //判断POST请求是否为空      if (!string.IsNullOrEmpty(PostData))      {        request.ContentType = "application/x-www-form-urlencoded";        request.Method = "POST";        using (var postStream = request.GetRequestStream())        {          var byteArray = Encoding.GetBytes(PostData);          postStream.Write(byteArray, 0, PostData.Length);          postStream.Close();        }      }      else      {        request.AllowWriteStreamBuffering = false;      }      try      {        using (var response = request.GetResponse() as HttpWebResponse)        {          if (response != null)          {            if (response.StatusCode != HttpStatusCode.OK)            {              Trace.TraceError(string.Concat("请求地址:", request.RequestUri, " 失败,HttpStatusCode",                response.StatusCode));              return string.Empty;            }            using (var streamResponse = response.GetResponseStream())            {              if (streamResponse != null)              {                if (!IsText(response.ContentType))                {                  var contentEncodingStr = response.ContentEncoding;                  var contentEncoding = Encoding;                  if (!string.IsNullOrEmpty(contentEncodingStr))                    contentEncoding = Encoding.GetEncoding(contentEncodingStr);                  var streamRead = new StreamReader(streamResponse, contentEncoding);                  var str = streamRead.ReadToEnd();                  if (CallBackAction != null && !String.IsNullOrEmpty(str))                    CallBackAction.BeginInvoke(str, request.RequestUri.ToString(), (s) => { }, null);                  return str;                }                //创建并指定文件夹                var fileName = string.Concat(DateTime.Now.ToString("yyyyMMdd"), "/", DateTime.Now.ToString("yyyyMMddHHmmssffff"),                  Path.GetExtension(request.RequestUri.AbsoluteUri));                var fileDirectory = Path.Combine(FileSavePath, DateTime.Now.ToString("yyyyMMdd"));                if (!Directory.Exists(fileDirectory))                  Directory.CreateDirectory(fileDirectory);                try                {                  //下载文件                  using (var fileStream = new FileStream(Path.Combine(FileSavePath, fileName), FileMode.Create))                  {                    var buffer = new byte[2048];                    int readLength;                    do                    {                      readLength = streamResponse.Read(buffer, 0, buffer.Length);                      fileStream.Write(buffer, 0, readLength);                    } while (readLength != 0);                  }                  if (CallBackAction != null && !String.IsNullOrEmpty(fileName))                    CallBackAction.BeginInvoke(fileName, request.RequestUri.ToString(), (s) => { }, null);                  return fileName;                }                catch (IOException ex)                {                  throw new IOException(ex.Message, ex);                }              }            }            response.Close();          }        }      }      catch (WebException ex)      {        Trace.TraceError(string.Concat("请求地址:", request.RequestUri, " 失败信息:", ex.Message));        var toUrl = request.RequestUri.ToString();        if (_urlTryList.TryGetValue(toUrl, out tryTimes))        {          _urlTryList.TryUpdate(toUrl, tryTimes, tryTimes - 1);          if (tryTimes - 1 <= 0)          {            _urlTryList.TryRemove(toUrl, out tryTimes);            Trace.TraceError(string.Concat("请求地址重试失败:", request.RequestUri));            return string.Empty;          }          SyncRequest(toUrl);        }      }      finally      {        request.Abort();      }      return string.Empty;    }

    以上就是对相关概念和代码的解析。有写的不到位的地方,敬请谅解。