7.5 Java与网络

  Java语言从其诞生开始,就和网络紧密联系在一起。在1995年的Sun World大会上,当时占浏览器市场份额绝对领先的网景公司宣布在浏览器中支持Java,从而引起一系列的公司产品对Java提供支持,使得Java很快成为一种流行的语言。之后,Java在面向企业的服务器平台取得了广泛的成功。而如今,在移动互联的世界,随着安卓的异军突起,Java与网络的关系又向前迈进了一步。

7.5.1 IP地址类

  在TCP/IP协议族中,我们是通过IP地址来标识网络上的一台主机(含网络设备)的。如果想获取自己主机的IP地址,可以通过打开“Internet协议版本4(TCP/IPv4)属性”对话框方式查看(必须是设置固定IP地址,而不是自动获取IP地址),还可以通过ipconfig命令查看。假设需要在程序中获取本机的IP地址,该如何编写代码呢?

  通过查阅JDK API文档获悉,在Java中,使用java.net包下的InetAddress类表示互联网协议的IP地址。下面的案例演示了如何获得本地主机的IP地址。具体代码如下:

  1. import java.net.*;
  2. public class TestGetIP{
  3. public static void main(String args[]) {
  4. InetAddress myIP = null;
  5. try{
  6. //通过InetAddress类的静态方法,返回本地主机对象
  7. myIP = InetAddress.getLocalHost();
  8. }catch(Exception e){
  9. e.printStackTrace();
  10. }
  11. //通过InetAddress类的getHostAddress()方法获得IP地址字符串
  12. System.out.println(myIP.getHostAddress());
  13. }
  14. }

  编译、运行程序,显示出本地主机的IP地址。如果不仅想获得本地主机的IP地址,还想根据用户输入的域名,获取这个域名在互联网上的IP地址,下面的代码演示了此功能:

  1. import java.util.Scanner;
  2. import java.net.*;
  3. public class TestGetIP2{
  4. public static void main(String args[]) {
  5. InetAddress sohuIP = null;
  6. Scanner input = new Scanner(System.in);
  7. System.out.print("请输入要查询IP地址的域名:");
  8. String dName = input.next();
  9. try{
  10. //通过InetAddress类的静态方法,返回指定域名的IP地址对象
  11. sohuIP = InetAddress.getByName(dName);
  12. }catch(Exception e){
  13. e.printStackTrace();
  14. }
  15. System.out.println("域名:" + dName + " 对应的IP地址为:" + sohuIP.getHostAddress());
  16. }
  17. }

  编译、运行程序,其运行结果如图7.4所示。

7.5 Java与网络 - 图1


图7.4 获取指定域名的IP地址

  上面的两个例子中,创建的InetAddress类对象都不是使用构造方法new出这个对象,而是通过InetAddress类的静态方法获取的。下面列出了通过InetAddress类的静态方法获取InetAddress类对象的方法。

  • InetAddress[] getAllByName(String host)

  在给定主机名的情况下,根据系统上配置的名称服务返回其IP地址所组成的数组。

  • InetAddress getByAddress(byte[] addr)

  在给定原始IP地址的情况下,返回InetAddress对象。

  • InetAddress getByAddress(String host, byte[] addr)

  根据提供的主机名和IP地址,创建InetAddress对象。

  • InetAddress getByName(String host)

  在给定主机名的情况下,返回InetAddress对象。

  • InetAddress getLocalHost()

  返回本地主机InetAddress对象。

  InetAddress类的其他常用方法有以下几种。

  • byte[] getAddress()

  返回此InetAddress对象的原始IP地址。

  • String getCanonicalHostName()

  返回此 IP 地址的完全限定域名。完全限定域名是指主机名加上全路径,全路径中列出了序列中所有域成员。

  • String getHostAddress()

  返回 IP 地址字符串。

  • String getHostName()

  返回此 IP 地址的主机名。

7.5.2 URL类

  Java提供的网络功能的相关类主要有三个,它们分别是URL、Socket和Datagram,其中URL是这三个类中层次级别最高或者说封装最多的类,通过URL类可以直接发送或读取网络上的数据。

  URL类代表一个统一资源定位符,它是指向互联网资源的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。

  通常,URL可分成几个部分。例如http://baike.baidu.com/view/29.htm,指示使用的协议为HTTP(超文本传输协议),并且该信息驻留在一台名为baike.baidu.com的主机上,主机上的信息名称为/view/29.htm。

  URL 可选择指定一个端口号,用于建立到远程主机 TCP 连接的端口号,例如http://127.0.0.1: 8080/examples/index.html。如果未指定该端口号,则使用协议默认的端口,HTTP协议的默认端口为80。

  URL 后面可能还跟有一个片段,也称为引用。该片段由井字符“#”指示,后面跟有更多的字符。例如http://java.sun.com/index.html#chapter1。使用此片段的目的在于表明,在获取到指定的资源后,应用程序需要使用文档中附加有chapter1标记的部分。

7.5 Java与网络 - 图2


图7.5 网络上指定资源页面

  下面通过一个案例来演示如何获取网络上指定资源(http://127.0.0.1:8080/examples/index.html)的信息。这个页面的具体内容如图7.5所示,其HTML代码如下:

  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
  2. <HTML>
  3. <HEAD>
  4. <TITLE>Apache Tomcat Examples</TITLE>
  5. <META http-equiv=Content-Type content="text/html">
  6. </HEAD>
  7. <BODY>
  8. <P>
  9. <H3>Apache Tomcat Examples</H3>
  10. </P>[[张彬1\]](#_msocom_1)
  11. <ul>
  12. <li><a href="servlets">Servlets examples</a></li>
  13. <li><a href="jsp">JSP Examples</a></li>
  14. </ul>
  15. </BODY>
  16. </HTML>

  这个案例的具体需求为先输入要定位的URL地址,然后再输入要显示哪个页面标签元素的内容,程序显示该标签的具体内容,具体代码如下。

  1. import java.util.Scanner;
  2. import java.net.*;
  3. import java.io.*;
  4. public class TestURL{
  5. public static void main(String args[]){
  6. URL tURL = null;
  7. BufferedReader in = null;
  8. Scanner input = new Scanner(System.in);
  9. System.out.print("请输入要定位的URL地址:");
  10. String url = input.next();
  11. System.out.print("请输入要显示哪个页面标签元素的内容:");
  12. String iStr = input.next();
  13. try
  14. {
  15. //通过URL字符串创建URL对象
  16. tURL = new URL(url);
  17. in = new BufferedReader(new InputStreamReader(tURL.openStream()));
  18. String s;
  19. while ((s = in.readLine()) != null){
  20. if(s.contains(iStr))
  21. System.out.println(s);
  22. }
  23. }catch(Exception e)
  24. {
  25. e.printStackTrace();
  26. }
  27. }
  28. }

  编译、运行程序,先后输入http://127.0.0.1:8080/examples/index.html和TITLE,其运行结果如图7.6所示。

7.5 Java与网络 - 图3


图7.6 URL类使用

7.5.3 URLConnection类

  前面介绍的URL类代表的是一个网络资源的位置,而接下来要介绍的URLConnection代表的是一种连接。此类的实例可用于读取和写入对应URL 引用的资源。通常,创建一个到URL的连接URLConnection的对象需要以下几个步骤。

  (1)通过在 URL 上调用openConnection()方法创建连接对象。

  (2)设置参数和一般请求属性。

  (3)使用connect()方法建立到远程对象的实际连接。

  (4)远程对象变为可用,其中远程对象的头字段和内容变为可访问。

  URLConnection类有下列属性作为参数可以设置:

  boolean doInput:将 doInput 标志设置为 true,指示应用程序要从 URL 连接读取数据,此属性的默认值为 true。此属性由 setDoInput()方法设置,其值由getDoInput()方法返回。

  boolean doOutput:将doOutput标志设置为 true,指示应用程序要将数据写入 URL 连接,此属性的默认值为false。此属性由setDoOutput()方法设置,其值由getDoOutput()方法返回。

  long ifModifiedSince:有些网络协议支持跳过对象获取,除非该对象在某个特定时间点之后又进行了修改。其值表示距离格林尼治标准时间1970年 1 月 1 日的毫秒数,只有在该时间之后又进行了修改时,才获取该对象。此属性的默认值为0,表示必须一直进行获取。此属性由setIfModifiedSince()方法设置,其值由getIfModifiedSince()方法返回。

  boolean useCaches:如果其值为true,则只要有条件就允许协议使用缓存;如果其值为false,则该协议始终必须获得此对象的新副本,其默认值为上一次调用setDefaultUseCaches()方法时给定的值。此属性由setUseCaches()方法设置,其值由getUseCaches()方法返回。

  boolean allowUserInteraction:如果其值为true,则在允许用户交互(例如弹出一个验证对话框)的上下文中对此URL进行检查;如果其值为false,则不允许有任何用户交互,其默认值为上一次调用setDefaultAllowUserInteraction()方法时所用的参数的值。使用setAllowUserInteraction()方法可对此属性的值进行设置,其值由getAllowUserInteraction()方法返回。

  URLConnection类还有两个属性connected和url,分别表示是否创建到指定 URL 的通信链接和该URLConnection类在互联网上打开的远程对象。

  另外,可以使用setRequestProperty(String key, String value)方法设置一般请求属性,如果已存在具有该关键字的属性,则用新值改写原值。

  下面通过一个案例,简要说明URLConnection类的使用。URLConnection类里涉及的一些知识现在还没有涉及,在阅读下面的代码时如果有不明白的地方,通过后面课程的学习会逐步理解。

  1. import java.net.*;
  2. import java.io.*;
  3. public class TestURLConnection{
  4. public static void main(String args[]){
  5. try{
  6. //(1)通过在URL上调用openConnection()方法创建连接对象
  7. URL url = new URL("http://127.0.0.1:8080/examples/index.html");
  8. //根据URL获取URLConnection对象
  9. URLConnection urlC = url.openConnection();
  10. //请求协议是HTTP协议,故可转换为HttpURLConnection对象
  11. HttpURLConnection hUrlC = (HttpURLConnection)urlC;
  12. //(2)设置参数和一般请求属性
  13. //请求方法如果是POST,参数要放在请求体里,所以要向hUrlC输出参数
  14. hUrlC.setDoOutput(true);
  15. //设置是否从httpUrlConnection读入,默认情况下是true
  16. hUrlC.setDoInput(true);
  17. //请求如果是POST,不能使用缓存
  18. hUrlC.setUseCaches(false);
  19. //设置Content-Type属性
  20. hUrlC.setRequestProperty("Content-Type", "text/plain; charset=utf-8");
  21. //设定请求的方法为POST,默认是GET
  22. hUrlC.setRequestMethod("POST");
  23. //(3)使用connect方法建立到远程对象的实际连接
  24. hUrlC.connect();
  25. //(4)远程对象变为可用
  26. //通过HttpURLConnection获取输出输入流,可根据需求进一步操作
  27. OutputStream outStrm = hUrlC.getOutputStream();
  28. InputStream inStrm = hUrlC.getInputStream();
  29. //省略若干代码
  30. }catch(Exception e){
  31. e.printStackTrace();
  32. }
  33. }
  34. }