您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 企业文化 > 第14章Java网络编程
第14章Java网络编程用Java开发网络软件非常方便且功能强大,Java的这种力量来源于他独有的一套强大的用于网络的API,这些API是一系列的类和接口,均位于包java.net和javax.net中。在本章中我们将首先介绍Java网络编程中扮演重要角色的InetAddress类,再介绍套接字(Socket)的概念,同时以实例说明如何使用NetworkAPI操纵套接字。最后简单介绍在非连接的UDP协议下如何进行网络通讯。在完成本章的学习后,你就可以编写网络低端通信软件了。14.1InetAddress类简介InetAddress类在网络API套接字编程中扮演了一个重要角色。InetAddress描述了32位或128位IP地址,要完成这个功能,InetAddress类主要依靠Inet4Address和Inet6Address两个支持类。这三个类是继承关系,InetAddrress是父类,Inet4Address和Inet6Address是子类。由于InetAddress类只有一个构造函数,而且不能传递参数,所以不能直接创建InetAddress对象,比如下面的语句就是错误的:InetAddressia=newInetAddress();但我们可以通过下面的5个静态方法来创建一个InetAddress对象或InetAddress数组:(1)getAllByName(Stringhost)方法返回一个InetAddress对象数组的引用,每个对象包含一个表示相应主机名的单独的IP地址,这个IP地址是通过host参数传递的,对于指定的主机,如果没有IP地址存在,那么这个方法将抛出一个UnknownHostException异常对象。(2)getByAddress(byte[]addr)方法返回一个InetAddress对象的引用,这个对象包含了一个IPv4地址或IPv6地址,IPv4地址是一个4字节地址数组,IPv6地址是一个16字节地址数组,如果返回的数组既不是4字节的也不是16字节的,那么方法将会抛出一个UnknownHostException异常对象。(3)getByAddress(Stringhost,byte[]addr)方法返回一个InetAddress对象的引用,这个InetAddress对象包含了一个由host和4字节的addr数组指定的IP地址,或者是host和16字节的addr数组指定的IP地址,如果这个数组既不是4字节的也不是16字节的,那么该方法将抛出一个UnknownHostException异常对象。(4)getByName(Stringhost)方法返回一个InetAddress对象,该对象包含了一个与host参数指定的主机相对应的IP地址,对于指定的主机,如果没有IP地址存在,那么方法将抛出一个UnknownHostException异常对象。(5)getLocalHost()方法返回一个InetAddress对象,这个对象包含了本地主机的IP地址,考虑到本地主机既是客户程序主机又是服务器程序主机,为避免混乱,我们将客户程序主机称为客户主机,将服务器程序主机称为服务器主机。上面讲到的方法均提到返回一个或多个InetAddress对象的引用,实际上每一个方法都要Java语言程序设计教程244返回一个或多个Inet4Address/Inet6Address对象的引用,调用者不需要知道引用的子类型,相反调用者可以使用返回的引用调用InetAddress对象的非静态方法,包括子类型的多态以确保重载方法被调用。InetAddress和它的子类型对象处理主机名到主机IPv4或IPv6地址的转换,要完成这个转换需要使用域名系统,下面的代码示范了如何通过调用getByName(Stringhost)方法获得InetAddress子类对象的方法,这个对象包含了与host参数相对应的IP地址:InetAddressia=InetAddress.getByName();一旦获得了InetAddress子类对象的引用就可以调用InetAddress的各种方法来获得InetAddress子类对象中的IP地址信息。例如,可以通过调用getCanonicalHostName()从域名服务中获得标准的主机名;getHostAddress()获得IP地址;getHostName()获得主机名;isLoopbackAddress()判断IP地址是否是一个loopback地址。例14.1InetAddress示例程序InetAddressDemo.javaimportjava.net.*;classInetAddressDemo{publicstaticvoidmain(String[]args)throwsUnknownHostException{Stringhost=localhost;if(args.length==1)host=args[0];InetAddressia=InetAddress.getByName(host);System.out.println(CanonicalHostName=+ia.getCanonicalHostName());System.out.println(HostAddress=+ia.getHostAddress());System.out.println(HostName=+ia.getHostName());System.out.println(IsLoopbackAddress=+ia.isLoopbackAddress());}}在Eclipse中进行调试时,控制台窗口输出的结果如下:图14-1InetAddressDemo.java程序的运行结果InetAddressDemo给了用户一个指定主机名作为命令行参数的选择,如果没有主机名被指定,那么将使用localhost(客户机的),InetAddressDemo通过调用getByName(Stringhost)方法获得一个InetAddress子类对象的引用,通过这个引用获得了标准主机名、主机地址、主机名以及IP地址是否是loopback地址的输出。第第14章Java网络编程24514.2面向连接的流式套接字14.2.1什么是套接字NetworkAPI主要用于基于TCP/IP网络的Java程序与其他程序通信中,它依靠Socket进行通信。Socket可以看成在两个程序进行通信连接中的一个端点,一个程序将一段信息写入Socket中,该Socket将这段信息发送给另外一个Socket中,使这段信息能传送到其他程序中。无论何时,在两个网络应用程序之间发送和接收信息时都需要建立一个可靠的连接,流套接字依靠TCP协议来保证信息正确到达目的地。实际上,IP包有可能在网络中丢失或者在传送过程中发生错误,任何一种情况发生,作为接收方的TCP将联系发送方TCP重新发送这个IP包。这就是所谓的在两个流套接字之间建立可靠的连接。流套接字在C/S程序中扮演一个必需的角色,客户机程序(需要访问某些服务的网络应用程序)创建一个扮演服务器程序的主机的IP地址和服务器程序(为客户端应用程序提供服务的网络应用程序)的端口号的流套接字对象。客户端流套接字的初始化代码将IP地址和端口号传递给客户端主机的网络管理软件,管理软件将IP地址和端口号通过NIC传递给服务器端主机;服务器端主机读到经过NIC传递来的数据,然后查看服务器程序是否处于监听状态,这种监听依然是通过套接字和端口来进行的;如果服务器程序处于监听状态,那么服务器端网络管理软件就向客户机网络管理软件发出一个积极的响应信号,接收到响应信号后,客户端流套接字初始化代码就给客户程序建立一个端口号,并将这个端口号传递给服务器程序的套接字(服务器程序将使用这个端口号识别传来的信息是否是属于客户程序),同时完成流套接字的初始化。如果服务器程序没有处于监听状态,那么服务器端网络管理软件将给客户端传递一个消极信号,收到这个消极信号后,客户程序的流套接字初始化代码将抛出一个异常对象并且不建立通信连接,也不创建流套接字对象。这种情形就像打电话一样,当有人的时候通信建立,否则电话将被挂断。这部分的工作包括了相关联的三个类:InetAddress、Socket和ServerSocket。InetAddress对象描绘了32位或128位IP地址,我们在本章第一节中已经详细介绍过;Socket对象代表了客户程序流套接字;ServerSocket代表了服务程序流套接字,这三个类均位于java.net包中。14.2.2ServerSocket类由于SocketDemo使用了流套接字,所以服务程序也要使用流套接字,这就要创建一个ServerSocket对象。ServerSocket有几个构造函数,最简单的是:ServerSocket(intport);当使用ServerSocket(intport)创建一个ServerSocket对象时,port参数传递端口号,这个端口就是服务器监听连接请求的端口。如果在这时出现错误将抛出IOException异常对象,否则将创建ServerSocket对象并开始准备接收连接请求。接下来服务程序进入无限循环之中。无限循环从调用ServerSocket的accept()方法开始,在调用开始后accept()方法将导致调用线程阻塞直到连接建立。在建立连接后accept()返回一个最近创建的Socket对象,该Socket对象绑定了客户程序的IP地址或端口号。由于存在单个服务程序与多个客户程序通信的可能,所以服务程序响应客户程序不应该Java语言程序设计教程246花很多时间,否则客户程序在得到服务前有可能花很多时间来等待通信的建立,然而服务程序和客户程序的会话有可能是很长的(这与电话类似),因此为加快对客户程序连接请求的响应,典型的方法是服务器主机运行一个后台线程,这个后台线程处理服务程序和客户程序的通讯。为了示范我们在上面谈到的概念并完成SocketDemo程序,下面我们创建一个ServerDemo程序。该程序将创建一个ServerSocket对象来监听端口10000的连接请求,如果成功,服务程序将等待连接输入,开始一个线程处理连接,并响应来自客户程序的命令。例14.2ServerSocket示例程序ServerDemo.javaimportjava.io.*;importjava.net.*;importjava.util.*;classServerDemo{publicstaticvoidmain(String[]args)throwsIOException{System.out.println(Serverstarting...\n);ServerSocketserver=newServerSocket(10000);while(true){Sockets=server.accept();System.out.println(AcceptingConnection...\n);newServerThread(s).start();}}}classServerThreadextendsThread{privateSockets;ServerThread(Sockets){this.s=s;}publicvoidrun(){BufferedReaderbr=null;PrintWriterpw=null;try{InputStreamReaderisr;isr=newInputStreamReader(s.getInputStream());br=newBufferedReader(isr);pw=newPrintWriter(s.getOutputStream(),true);Calendarc=Calendar.getInstance();do{Stringcmd=br.readLine();if(cmd==null)break;cmd=cmd.toUpperCase()
本文标题:第14章Java网络编程
链接地址:https://www.777doc.com/doc-2243235 .html