您的位置:首页 > 编程语言 > C#

C#之WebClient学习笔记

2013-11-28 23:29 176 查看
        最近在用C#做项目,需要和HTTP服务器通信,网上的资料很多,样例代码不少,但为了实地验证一下WebClient的用法,所以准备了一套简单的环境。下面记录了验证WebClient类使用方法的笔记。

基本环境

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,这也是一大发现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: