C#之WebClient学习笔记
2013-11-28 23:29
176 查看
最近在用C#做项目,需要和HTTP服务器通信,网上的资料很多,样例代码不少,但为了实地验证一下WebClient的用法,所以准备了一套简单的环境。下面记录了验证WebClient类使用方法的笔记。
代码里把request对象里能输出的信息都通过命令行输出出来,方便观察行为。
2、event类型的对象可以增加多个事件处理器方法,处理器方法执行时的顺序和增加的顺序相同。
3、using指令,用于释放系统资源。这个语法非常好用,不需要写恶心的try catch finally。本来Java 7提供了类似的语法,只可惜我所在的项目组还在使用JDK1.6版本,所以新的语法特性带来的便利暂时还享受不到。
4、和Java的字符串格式化方法相比,C#提供的字符串格式化方法在使用上还是非常方便的,一般场景下只需要写{0},而Java则需要写%1$s,省心不少。
2、从WebClient类暴露的方法看,应当是对类HttpWebRequest和HttpWebResponse的封装,结果是更加好用。直接使用HttpWebRequest类虽然很灵活,但是在异步处理消息时,由于事件没有封装在一起,其实是蛮难用的,代码比较丑。
3、WebClient类通过OpenWriteAsync和OpenWrite方法可以显式控制HTTP方法,比如使用POST还是GET来传输数据,比较方便。但使用这两个方法时无法获取到HTTP服务器端返回的数据,如果上传数据结束之后还希望提取到HTTP响应消息体里的信息,则最好使用UploadDataXXX之类的方法。
2、GET和POST消息里,都可以在URL后面增加QueryString,这也是一大发现。
基本环境
HTTP服务器
由于对Java了解更多,所以决定使用tomcat来做HTTP服务器。从官网下载了新版本的tomcat和j2ee Eclipse,准备了Web开发环境,开发一个简单的Servlet,专用于接收HTTP请求消息,分析消息的内容。在Eclipse里搭建web开发环境的过程网上有很多,所以这里不详细写。Servlet的源码如下。package com.jackie; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.Collection; import java.util.Enumeration; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; /** * Servlet implementation class Player */ @WebServlet("/Player") public class Player extends HttpServlet { private static final long serialVersionUID = 1L; /** * Default constructor. */ public Player() { } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ @Override protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { System.out.println("in doGet"); process(request, response); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ @Override protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { System.out.println("in doPost"); process(request, response); } private void process(final HttpServletRequest request, final HttpServletResponse response) throws IOException, IllegalStateException, ServletException { final Enumeration<String> headers = request.getHeaderNames(); while (headers.hasMoreElements()) { final String headerName = headers.nextElement(); final String headerValue = request.getHeader(headerName); System.out.println("HEADER, " + headerName + "=" + headerValue); } final Enumeration<String> attributes = request.getAttributeNames(); while (attributes.hasMoreElements()) { final String attrName = attributes.nextElement(); final Object attrValue = request.getAttribute(attrName); System.out.println("ATTRIBUTE, " + attrName + "=" + attrValue); } final int contentLength = request.getContentLength(); System.out.println("ContentLength=" + contentLength); final InputStream stream = request.getInputStream(); try (final BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) { String line = null; while ((line = reader.readLine()) != null) { System.out.println("INPUT, line=" + line); } } System.out.println("QueryString=" + request.getQueryString()); System.out.println("RequestUrl=" + request.getRequestURL()); System.out.println("PathInfo=" + request.getPathInfo()); System.out.println("PathInfo=" + request.getPathTranslated()); final Collection<Part> parts = request.getParts(); for (final Part part : parts) { System.out.println("Part, name=" + part.getName() + ", value=" + part.getContentType()); } response.setStatus(HttpServletResponse.SC_OK); final String out = "hello1111"; final OutputStream os = response.getOutputStream(); os.write(out.getBytes()); response.setContentLength(out.length()); response.setContentType("txt/html"); } }
代码里把request对象里能输出的信息都通过命令行输出出来,方便观察行为。
HTTP客户端
下载官方的C#开发环境,VS C# express 2010版本,安装完成之后需要注册,否则只有30天使用期限。创建一个命令行工程,加入如下代码。using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Threading; namespace ConsoleApplication { class Program { static void Main(string[] args) { string url = "http://localhost:8080/Player"; using (WebClient wc = new WebClient()) { wc.QueryString.Add("aaa", "bbb"); wc.QueryString.Add("aaa1", "bbb1"); wc.QueryString.Add("aaa2", "bbb2"); wc.Proxy = null; wc.Headers.Add("wc", "value"); string data = wc.DownloadString(url); Console.WriteLine("data {0}", data); wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted); wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted2); wc.DownloadStringAsync(new Uri(url)); Thread.Sleep(2000); byte[] buffer = wc.DownloadData(url); data = Encoding.UTF8.GetString(buffer); Console.WriteLine("data1 {0}", data); wc.DownloadDataCompleted += new DownloadDataCompletedEventHandler(wc_DownloadDataCompleted); wc.DownloadDataAsync(new Uri(url)); Thread.Sleep(2000); } } static void wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e) { if (e.Error != null) { Console.WriteLine("error {0}", e.Error.Message); return; } string data = Encoding.UTF8.GetString(e.Result); Console.WriteLine("wc_DownloadDataCompleted {0}", data); } static void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { if (e.Error != null) { Console.WriteLine("error {0}", e.Error.Message); return; } Console.WriteLine("wc_DownloadStringCompleted {0}", e.Result); } static void wc_DownloadStringCompleted2(object sender, DownloadStringCompletedEventArgs e) { if (e.Error != null) { Console.WriteLine("error {0}", e.Error.Message); return; } Console.WriteLine("wc_DownloadStringCompleted2 {0}", e.Result); } } }
收获
之前一直使用Java来做C/S架构的应用,其它技术了解不多,感觉可以学到不少东东。C#相关
1、event类型只允许有+=和-=两种运算,换句话说就是只能增加和删除事件处理方法,其它的运算都是非法的。这一点比较有用,假如支持=运算的话,会在增加事件处理器的时候,意外的把已增加的事件处理器删除掉,由此可见,C#在设计时已经屏蔽了容易出错的运算行为。2、event类型的对象可以增加多个事件处理器方法,处理器方法执行时的顺序和增加的顺序相同。
3、using指令,用于释放系统资源。这个语法非常好用,不需要写恶心的try catch finally。本来Java 7提供了类似的语法,只可惜我所在的项目组还在使用JDK1.6版本,所以新的语法特性带来的便利暂时还享受不到。
4、和Java的字符串格式化方法相比,C#提供的字符串格式化方法在使用上还是非常方便的,一般场景下只需要写{0},而Java则需要写%1$s,省心不少。
WebClient相关
1、 这个类封装了HTPP Get消息相关的使用接口,对一个操作,同时提供了同步接口和异步接口,比如样例代码中的DownloadString和DownloadStringAsync。同时封装了事件完成之后的回调处理器,使用上非常方便。只是第一次看到的时候感觉不习惯,因为方法的命名和事件的处理方式和Java语言有不少差异。另外看惯了JDK自带的DOC文档,再回来阅读MSDN,也不太习惯,找想要的资料时比较吃力。2、从WebClient类暴露的方法看,应当是对类HttpWebRequest和HttpWebResponse的封装,结果是更加好用。直接使用HttpWebRequest类虽然很灵活,但是在异步处理消息时,由于事件没有封装在一起,其实是蛮难用的,代码比较丑。
3、WebClient类通过OpenWriteAsync和OpenWrite方法可以显式控制HTTP方法,比如使用POST还是GET来传输数据,比较方便。但使用这两个方法时无法获取到HTTP服务器端返回的数据,如果上传数据结束之后还希望提取到HTTP响应消息体里的信息,则最好使用UploadDataXXX之类的方法。
HTTP服务
1、QueryString是什么,在验证WebClient的时候发现可以控制HTTP请求的QueryString,简单验证之后发现原来是URL之后的参数列表,比如有http://1.1.1.1/player?aaa=ccc&bbb=ddd,那么QueryString即是aaa=ccc&bbb=ddd。2、GET和POST消息里,都可以在URL后面增加QueryString,这也是一大发现。
相关文章推荐
- C#开发学习笔记:利用WebClient下载文件
- The Key of C# 学习笔记(你今天学到了什么2004-10)
- C#学习笔记1:正则表达式和数据库连接
- C#学习笔记(3)_C#教程
- C#学习笔记27——WorkFlow
- C#学习笔记14:面向对象继承的特点和里氏转换
- UNITY 2D学习笔记(二):C#脚本编写
- c#字符串学习笔记一
- [C#] 类型学习笔记二:详解对象之间的比较
- 我的C#学习笔记(1)
- C#中的lock、Monitor、Mutex学习笔记
- C#开发学习笔记:利用XML配置文件连接数据库
- c#学习笔记(四) get-set
- c#之链表学习笔记
- C#控件学习笔记
- C#学习回顾笔记一:C#的Console.WriteLine()
- C#学习笔记(事件)
- 黑马程序员之C#学习笔记:求一个字符串中各个字符出现的次数
- C#学习笔记——SerialPort类
- C++学习笔记-类定义的注意事项和C#的区别