欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#中HttpWebRequest、WebClient、HttpClient的使用详解

程序员文章站 2023-02-20 21:32:17
httpwebrequest: 命名空间: system.net,这是.net创建者最初开发用于使用http请求的标准类。使用httpwebrequest可以让开发者控制请求/响...

httpwebrequest:

命名空间: system.net,这是.net创建者最初开发用于使用http请求的标准类。使用httpwebrequest可以让开发者控制请求/响应流程的各个方面,如 timeouts, cookies, headers, protocols。另一个好处是httpwebrequest类不会阻塞ui线程。例如,当您从响应很慢的api服务器下载大文件时,您的应用程序的ui不会停止响应。httpwebrequest通常和webresponse一起使用,一个发送请求,一个获取数据。httpwebrquest更为底层一些,能够对整个访问过程有个直观的认识,但同时也更加复杂一些。

     //post方法
    public static string httppost(string url, string postdatastr)
    {
      httpwebrequest request = (httpwebrequest)webrequest.create(url);
      request.method = "post";
      request.contenttype = "application/x-www-form-urlencoded";
      encoding encoding = encoding.utf8;
      byte[] postdata = encoding.getbytes(postdatastr);
      request.contentlength = postdata.length;
      stream myrequeststream = request.getrequeststream();
      myrequeststream.write(postdata, 0, postdata.length);
      myrequeststream.close();
      httpwebresponse response = (httpwebresponse)request.getresponse();
      stream myresponsestream = response.getresponsestream();
      streamreader mystreamreader = new streamreader(myresponsestream, encoding);
      string retstring = mystreamreader.readtoend();
      mystreamreader.close();
      myresponsestream.close();

      return retstring;
    }
    //get方法
    public static string httpget(string url, string postdatastr)
    {
      httpwebrequest request = (httpwebrequest)webrequest.create(url + (postdatastr == "" ? "" : "?") + postdatastr);
      request.method = "get";
      request.contenttype = "text/html;charset=utf-8";
      httpwebresponse response = (httpwebresponse)request.getresponse();
      stream myresponsestream = response.getresponsestream();
      streamreader mystreamreader = new streamreader(myresponsestream, encoding.getencoding("utf-8"));
      string retstring = mystreamreader.readtoend();
      mystreamreader.close();
      myresponsestream.close();
      return retstring;
    }

webclient:

命名空间system.net,webclient是一种更高级别的抽象,是httpwebrequest为了简化最常见任务而创建的,使用过程中你会发现他缺少基本的header,timeoust的设置,不过这些可以通过继承httpwebrequest来实现。相对来说,webclient比webrequest更加简单,它相当于封装了request和response方法,不过需要说明的是,webclient和webrequest继承的是不同类,两者在继承上没有任何关系。使用webclient可能比httpwebrequest直接使用更慢(大约几毫秒),但却更为简单,减少了很多细节,代码量也比较少。

public class webclienthelper
  {
    public static string downloadstring(string url)
    {
      webclient wc = new webclient();
      //wc.baseaddress = url;  //设置根目录
      wc.encoding = encoding.utf8;  //设置按照何种编码访问,如果不加此行,获取到的字符串中文将是乱码
      string str = wc.downloadstring(url);
      return str;
    }
    public static string downloadstreamstring(string url)
    {
      webclient wc = new webclient();
      wc.headers.add("user-agent", "mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/76.0.3809.132 safari/537.36");
      stream objstream = wc.openread(url);
      streamreader _read = new streamreader(objstream, encoding.utf8);  //新建一个读取流,用指定的编码读取,此处是utf-8
      string str = _read.readtoend();
      objstream.close();
      _read.close();
      return str;
    }

    public static void downloadfile(string url, string filename)
    {
      webclient wc = new webclient();
      wc.downloadfile(url, filename);   //下载文件
    }

    public static void downloaddata(string url, string filename)
    {
      webclient wc = new webclient();
      byte [] bytes = wc.downloaddata(url);  //下载到字节数组
      filestream fs = new filestream(filename, filemode.create);
      fs.write(bytes, 0, bytes.length); 
      fs.flush();
      fs.close();
    }

    public static void downloadfileasync(string url, string filename)
    {
      webclient wc = new webclient();
      wc.downloadfilecompleted += downcompletedeventhandler;
      wc.downloadfileasync(new uri(url), filename);
      console.writeline("下载中。。。");
    }
    private static void downcompletedeventhandler(object sender, asynccompletedeventargs e)
    {
      console.writeline(sender.tostring());  //触发事件的对象
      console.writeline(e.userstate);
      console.writeline(e.cancelled);
      console.writeline("异步下载完成!");
    }

    public static void downloadfileasync2(string url, string filename)
    {
      webclient wc = new webclient();
      wc.downloadfilecompleted += (sender, e) =>
      {
        console.writeline("下载完成!");
        console.writeline(sender.tostring());
        console.writeline(e.userstate);
        console.writeline(e.cancelled);
      };
      wc.downloadfileasync(new uri(url), filename);
      console.writeline("下载中。。。");
    }
  }

httpclient:

httpclient是.net4.5引入的一个http客户端库,其命名空间为 system.net.http ,.net 4.5之前我们可能使用webclient和httpwebrequest来达到相同目的。httpclient利用了最新的面向任务模式,使得处理异步请求非常容易。它适合用于多次请求操作,一般设置好默认头部后,可以进行重复多次的请求,基本上用一个实例可以提交任何的http请求。httpclient有预热机制,第一次进行访问时比较慢,所以不应该用到httpclient就new一个出来,应该使用单例或其他方式获取httpclient的实例

单例模式:

单例模式(singleton pattern)这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

单例创建步骤:1、定义静态私有对象;2、定义私有构造函数;3、提供公共获取对象方法;

单例模式一般分为两种实现模式:懒汉模式、饿汉模式(以下为java代码实现)

懒汉模式:  默认不会实例化,什么时候用什么时候new

public class singleton { 
  private static singleton instance = null; 
  private singleton (){} 
 
  public static singleton getinstance() { 
  if (instance == null) { 
    instance = new singleton(); 
  } 
  return instance; 
  } 
}

这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。

饿汉模式:  类初始化时,会立即加载该对象,线程天生安全,调用效率高

public class singleton { 
  private static singleton instance = new singleton(); 
  private singleton (){} 
  public static singleton getinstance() { 
  return instance; 
  } 
}

双检锁/双重校验锁(dcl,即 double-checked locking):这种方式采用双锁机制,安全且在多线程情况下能保持高性能

public class singleton { 
  private volatile static singleton singleton; 
  private singleton (){} 
  public static singleton getsingleton() { 
  if (singleton == null) { 
    synchronized (singleton.class) { 
    if (singleton == null) { 
      singleton = new singleton(); 
    } 
    } 
  } 
  return singleton; 
  } 
}

httpclient:

public class httpclienthelper
  {
    private static readonly object lockobj = new object();
    private static httpclient client = null;
    public httpclienthelper() {
      getinstance();
    }
    public static httpclient getinstance()
    {

      if (client == null)
      {
        lock (lockobj)
        {
          if (client == null)
          {
            client = new httpclient();
          }
        }
      }
      return client;
    }
    public async task<string> postasync(string url, string strjson)//post异步请求方法
    {
      try
      {
        httpcontent content = new stringcontent(strjson);
        content.headers.contenttype = new system.net.http.headers.mediatypeheadervalue("application/json");
        //由httpclient发出异步post请求
        httpresponsemessage res = await client.postasync(url, content);
        if (res.statuscode == system.net.httpstatuscode.ok)
        {
          string str = res.content.readasstringasync().result;
          return str;
        }
        else
          return null;
      }
      catch (exception ex)
      {
        return null;
      }
    }

    public string post(string url, string strjson)//post同步请求方法
    {
      try
      {
        httpcontent content = new stringcontent(strjson);
        content.headers.contenttype = new system.net.http.headers.mediatypeheadervalue("application/json");
        //client.defaultrequestheaders.connection.add("keep-alive");
        //由httpclient发出post请求
        task<httpresponsemessage> res = client.postasync(url, content);
        if (res.result.statuscode == system.net.httpstatuscode.ok)
        {
          string str = res.result.content.readasstringasync().result;
          return str;
        }
        else
          return null;
      }
      catch (exception ex)
      {
        return null;
      }
    }

    public string get(string url)
    {
      try
      {
        var responsestring = client.getstringasync(url);
        return responsestring.result;
      }
      catch (exception ex)
      {
        return null;
      }
    }

  }

httpclient有预热机制,第一次请求比较慢;可以通过初始化前发送一次head请求解决:

_httpclient = new httpclient() { baseaddress = new uri(base_address) };

    //帮httpclient热身
    _httpclient.sendasync(new httprequestmessage {
        method = new httpmethod("head"), 
        requesturi = new uri(base_address + "/") })
      .result.ensuresuccessstatuscode();

三者区别列表:

C#中HttpWebRequest、WebClient、HttpClient的使用详解

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。