C#之WebClient学习笔记

        最近在用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,这也是一大发现。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小南家的青蛙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值