Java网络编程小结 URLConnection协议处理器

URL和URLConnection类

网络中的URL(Uniform Resource Locator)是统一资源定位符的简称。它表示Internet上某一资源的地址。通过URL我们可以访问Internet上的各种网络资源,比如最常见的WWW,FTP站点。 URL可以被认为是指向互联网资源的“指针”,通过URL可以获得互联网资源相关信息,包括获得URL的InputStream对象获取资源的信息,以及一个到URL所引用远程对象的连接URLConnection。 URLConnection对象可以向所代表的URL发送请求和读取URL的资源。通常,创建一个和URL的连接,需要如下几个步骤:

  1. 创建URL对象,并通过调用openConnection方法获得URLConnection对象;
  2. 设置URLConnection参数和普通请求属性;
  3. 向远程资源发送请求;
  4. 远程资源变为可用,程序可以访问远程资源的头字段和通过输入流来读取远程资源返回的信息。

这里需要重点讨论一下第三步:如果只是发送GET方式请求,使用connect方法建立和远程资源的连接即可;如果是需要发送POST方式的请求,则需要获取URLConnection对象所对应的输出流来发送请求。这里需要注意的是,由于GET方法的参数传递方式是将参数显式追加在地址后面,那么在构造URL对象时的参数就应当是包含了参数的完整URL地址,而在获得了URLConnection对象之后,就直接调用connect方法即可发送请求。而POST方法传递参数时仅仅需要页面URL,而参数通过需要通过输出流来传递。另外还需要设置头字段。

URLConnection是一个协议处理器中的一个类,它是表示指向URL所指定的资源的活动连接。主要用于两个方面,一个是与服务器(特别是HTTP服务器)的交互,可以用来查看服务器发送的首部,设置连接的属性,设置客户端的请求的首部等。利用它也可以实现POST和PUT方法来发送数据。另一个方面是Java的协议处理器机制的一部分。所谓的协议处理器就是将处理协议的细节从处理特定数据类型中分离出,会涉及到客户端与服务器端的交互,如生成正确的请求格式,解释与数据一起返回的首部等。

获取URLConnection
    根据一个已经创建的URL来通过openConnection来打开生成一个URLConnection,虽然利用url来获取,其实内部调用的是URLStreamHandler的openConnection,该方法是一个抽象方法,它返回的URLConnection会根据协议的类型返回,倘若是一个http url则就会返回一个HTTPURLConnection。
    URL url=new URL("http://www.baidu.com");
    URLConnection uc=url.openConnection();
    此时该uc并没有连接,本地与远程主机是无法进行收发数据的,需要调用uc.connect()方法来建立连接。不过在使用getInputStream(),getHeaderField()等其它要求的时候会首先自动调用这个方法。
    利用此URLConnection可以很容易读取来自服务器端的数据,只要其getInputStream。

URL和URLConnectin的区别
URLConnection提供了对于HTTP首部的访问
URLConnection可以配置客户端向服务器端发送的请求参数即首部
URLConnection可以利用POST,PUT等请求方法与服务器进行交互

读取服务器响应的首部
对于服务器响应的首部,当然这里都是以HTTP服务器响应为准,可以来获取响应中的首部字段。
Content-type,Content-length,Content-encoding,Date,Last-modified,Expires
可以利用getContentType()来获取数据的MIME类型,判断字符编码,并且以正常的格式显示出,如

String encoding="ISO-8859-1";//HTTP默认的编码方式
URL u=new URL(url);
URLConnection uc=u.openConnection();
 String type=uc.getContentType();
  //获取字符编码方式
  int star=type.indexOf("charset=");
    if(star!=-1)
         encoding=type.substring(star+8);
  System.out.println("CharSet:"+encoding);
  InputStream raw=uc.getInputStream();
   Reader r=new InputStreamReader(new BufferedInputStream(raw),encoding);

利用getContentLength来获取二进制文件大小,从而来下载文件

URLConnection uc=url.openConnection();
    String contentType=uc.getContentType();
    int contentLength=uc.getContentLength();
    if(contentType.startsWith("text/")||contentLength==-1)
    {
      throw new IOException("This is not a binary file");
    }

    InputStream raw=new BufferedInputStream(uc.getInputStream());
    byte[] data=new byte[contentLength];

    int bytesRead=0;
    int offset=0;
    while(offset<contentLength)
    {
      bytesRead=raw.read(data, offset, contentLength);
      if(bytesRead==-1)break;
      offset+=bytesRead;
    }

    raw.close();

    if(offset!=contentLength)
    {
      throw new IOException("Only read "+offset+ "bytes;Expected "+contentLength+" bytes");
    }

     //根据URL中获取文件路径的名,将获取的流写入到本地
    String file=url.getFile();
    int start=file.lastIndexOf("/");
    String filename=file.substring(start+1);

    FileOutputStream fout=new FileOutputStream(filename);
    fout.write(data);
    fout.flush();
    fout.close();

getHeaderField(String name);可以根据指定首部名来不区分大小写获取该名对应的值
getHeaderFieldKey(int n)和getHeaderField(int n)依此返回首部中的名和值,很有用

URL u=new URL(url);
URLConnection uc=u.openConnection();

for(int j=1;;j++)
{
  String header=uc.getHeaderField(j);
  if(header==null)break;//skip the loop
  System.out.println(uc.getHeaderFieldKey(j)+":"+header);
}

配置连接
所谓的配置主要就是定义了客户端如何向服务器做出请求。
一般客户端在默认情况下doInput为true,表示可以接受来自服务器端发送的数据,这些必须在URLConnection连接之前设置。如果想要利用POST和PUT进行交互就必须要设置doOutpu为true,默认是false

配置客户端发送的HTPP首部
客户端进行服务器访问的时候,有些协议需要加上首部,配置一些名值对,可以通过setRequestProperty(name,value)设置,多个值之间利用逗号隔开。

客户端利用POST来发送数据

package com.urlconnection;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.net.URLConnection;

//模拟表单提交处理
public class FormPoster {

  private URL url;
  private QueryString query=new QueryString();

  //必须要保证是http协议
  public FormPoster(URL url)
  {
            if(!url.getProtocol().toUpperCase().startsWith("HTTP"))
            {
             throw new IllegalArgumentException("Posting only works for http urls");
            }
            this.url=url;
  }

  public void add(String name,String value)
  {
    query.add(name, value);
  }

  public URL getURL()
  {
    return this.url;
  }

  public InputStream post()throws IOException
  {
    URLConnection uc=url.openConnection();
    uc.setDoOutput(true);
    Writer out=new OutputStreamWriter(uc.getOutputStream(),"ASCII");
    //POST行,Content-type和Content-length是由URLConnection发送的
    //只需要发送数据即可
    out.write(query.toString());
    out.write("\r\n\r\n");
    out.flush();
    out.close();

    return uc.getInputStream();
  }

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    String u="http://www.baidu.com";
    URL url=null;
    try{
        url=new URL(u);
    }catch(IOException e)
    {
    }
                 FormPoster poster=new FormPoster(url);
                 poster.add("hawk", "fdafda");
                 poster.add("good morning", "fdafa");

                 try{
                    InputStream in=poster.post();

                    //读取响应
                    InputStreamReader r=new InputStreamReader(in);
                    int c;
                    while((c=r.read())!=-1)
                    {
                     System.out.print((char)c);
                    }
                    in.close();
                 }catch(IOException ex)
                 {
                    System.err.println(ex);
                 }
  }

}

HTTPURLConnection
这个是一个专门操作http URL的类,继承子URLConnection,主要有7个请求的方法,
利用setRequestMethod(String method)设置不同的请求方法,默认是get,区分大小写
GET,从服务器端获取数据
POST,向服务器端提交表单
PUT,上传文件至服务器
HEAD,获取服务器端响应的头部
OPTIONS,查询服务器支持哪些请求方法
DELETE,删除服务器中的文件
TRACE,服务器返回客户端发送的HTTP首部,用于检测代理服务器对HTTP首部进行怎样修改
服务器响应的格式如下:
HTTP/1.1 200 OK
...
这个类添加了两个方法
getResponseMessage()获取响应码对应的消息,如OK
getResponseCode()获取响应码,如200

协议处理器
    协议处理器主要就是根据URL中的协议来找到合适的协议处理器来进行客户端与服务器端的交互。主要涉及四个类,具体类URL,抽象类URLConnection和URLStreamHandler,以及接口URLStreamHandlerFactory。协议处理器的流处理器总是根据指定的协议找到最适合的URLConnection
    要想自己建立协议处理器,需要编写两个URLConnection和URLStreamHandler的子类,然后创建一个URLStreamHandlerFactory。
    URLConnection子类主要处理与服务器交互,将服务器发送的数据转换为InputStream,将客户端发送的所有数据转换为OutputStream。URLStreamHandler子类主要将URL的字符串表示解析为各个部分,用这些部分来设置URL对象的各个部分,并且创建一个理解次URL协议的URLConnection。

协议处理器的基本流程如下:
1 程序先利用字符串构建某一个协议的URL对象,在创建URL模式中,只会验证是否识别URL模式,而不会对其格式的正确性进行检查
2 构造函数利用所传递的参数来确定URL的协议部分,如http
3 URL()构造函数以如下方式尝试进行找到给定的URLStreamHandler
   a 如果以前使用过此协议,从缓存中获取URLStreamHandler
   b 否则,若设置了URLStreamHandlerFactory,将此字符串传递给工厂 www.it165.net
   c 若两个都没有,则尝试实例化一个位于java.protocol.handler.pkgs属性列出的                  protocol.Handler的URLStreamHandler
   d 如果实例化失败,就尝试实例化一个位于sun.net.www.protocol中的protocol.Handler            的URLStreamHandler
   e 如果其中一个成功了,则设置属性字段handler字段。如果都不成功,则抛                        出MalformedURLException异常
4 程序调用URL对象的openConnection方法
5 URL会根据协议让URLStreamHandler返回一个适合于此URL的URLConnection
6 使用URLConnection进行与远程资源的交互

URLStreamHandler解析URL中字段的过程
URL(String)-->URL(URL,String)-->URL(URL,String,String)-->URLStreamHandler.parseURL()
-->URLStreamHandler.setURL()-->URL.set();
要新建立一个URLStreamHandler一般只需要修改openConnection方法即可,根据需要来修改parseURL
为每一个URLConnection子类重写一个connect方法,该方法包含了Socket的具体建立步骤。
再利用URLStreamHandlerFactory来注册这些流处理器

时间: 2024-10-05 04:25:00

Java网络编程小结 URLConnection协议处理器的相关文章

Java网络编程 - 基于UDP协议 实现简单的聊天室程序

最近比较闲,一直在抽空回顾一些Java方面的技术应用. 今天没什么事做,基于UDP协议,写了一个非常简单的聊天室程序. 现在的工作,很少用到socket,也算是对Java网络编程方面的一个简单回忆. 先看一下效果: 实现的效果可以说是非常非常简单,但还是可以简单的看到一个实现原理. "聊天室001"的用户,小红和小绿相互聊了两句,"聊天室002"的小黑无人理会,在一旁寂寞着. 看一下代码实现: 1.首先是消息服务器的实现,功能很简单: 将客户端的信息(进入了哪一个聊

java 网络编程 基于UDP协议的通信

使用UDP协议,写一个能在同一界面发送消息,并显示消息的聊天软件. 代码实现如下: package com.abel.socket; import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.util.Scanner; /* * 多线程在一个界面同时完成发送接收 * 1 发送send * ***创建

Java 网络编程 之 TCP协议

TCP协议 (服务器端程先启动,等待客户端连接) TCP协议是面向连接的通信协议,即在传输数据前先在发送端和接收端建立逻辑连接,然后再传输数据 保证传输数据的全性安,文件数据不易丢失 在JDK中提供了两个类用于实现TCP程序,一个是ServerSocket类,用于表示服务器端,一个是Socket类,用于表示客户端. 首先创建代表服务器端的ServerSocket对象,并等待客户端的连接, 然后创建代表客户端的Socket对象向服务器端发出连接请求,服务器端响应请求,客户端再次向服务器端发送确认信

Java网络编程(URL与URLConnection)

//URL package org.urldemo; import java.io.InputStream; import java.net.URL; import java.util.Scanner; public class URLDemo { public static void main(String[] args) throws Exception{ URL url = new URL("http","www.hut.edu.cn",80,"/c

Java 网络编程 UDP协议

网络编程 TCP/IP协议:多台计算机网络连接的规则 包括:TCP协议.IP协议.UDP协议和其它协议的协议组 层次结构: 链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤.网线提供的驱动.硬件方面的 网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络. 传输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议. 应用层:主要负责应用程序的协议,例如HTTP协议.F

java网络编程socket解析

转载:http://www.blogjava.net/landon/archive/2013/07/02/401137.html Java网络编程精解笔记2:Socket详解 Socket用法详解 在C/S通信模式中,client需要主动创建于server连接的Socket(套接字).服务器端收到了客户端的连接请求,也会创建与客户连接的Socket.Socket可看做是通信两端的收发器.server与client都通过Socket来收发数据. 1.构造Socket 1.Socket() 2.So

Java网络编程基础【转】

网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编程是比较复杂的系统工程,需要了解很多和网络相关的基础知识,其实这些都不是很必需的.首先来问一个问题:你 会打手机吗?很多人可能说肯定会啊,不就是按按电话号码,拨打电话嘛,很简单的事情啊!其实初学者如果入门网络编程的话也可以做到这么简单! 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.

第13篇-JAVA 网络编程

第13篇-JAVA 网络编程 每篇一句 比我强大的人都在努力我还有什么理由不拼命 初学心得 不去追逐你所渴求你将永远不会拥有 (笔者JEEP/711)[JAVA笔记 | 时间:2017-04-22| JAVA 网络编程 ] 1.网络编程基本概念 1.什么是计算机网络 计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备通过通信线路连接起来在网络操作系统网络管理软件及网络通讯协议的管理和协调下实现资源共享和信息传递的计算机系统 把分布在不同地理区域的计算机与专门的外部设备用通讯线路互

Java学习笔记—第十二章 Java网络编程入门

第十二章  Java网络编程入门 Java提供的三大类网络功能: (1)URL和URLConnection:三大类中最高级的一种,通过URL网络资源表达方式,可以很容易确定网络上数据的位置.利用URL的表示和建立,Java程序可以直接读入网络上所放的数据,或把自己的数据传送到网络的另一端. (2)Socket:又称"套接字",用于描述IP地址和端口(在Internet中,网络中的每台主机都有一个唯一的IP地址,而每台主机又通过提供多个不同端口来提供多种服务).在客户/服务器网络中,当客