1、第九章 Java语言网络编程,一、Java网络编程概述二、URL编程三、Socket编程,一、Java网络编程概述,一个程序员要想自如地进行网络编程,必须对网络的基本结构和概念有一定的了解。计算机之间通信要遵循一定的规则,通信协议就是计算机之间进行通信所要遵循的各种规则的集合。Internet网络通信主要使用的协议有适用于网络层的IP协议(IP协议使用IP地址使数据投递到正确的计算机上)、适用于传输层的TCP、UDP(TCP和UDP协议使用端口号PORT将数据投递给正确的应用程序)协议、适用于应用层的HTTP、FTP、SMTP、NNTP(通过HTTP、FTP、SMTP以及NNTP协议解释数据内
2、容)协议等。特别是在Internet上编程,则对TCP/IP协议要有一定的了解。,一、Java网络编程概述,在TCP/IP中有三个最常用的协议,理解这三个协议(IP,TCP,UDP)之间的交互对开发网络应用程序是至关重要的。 1. IP网间协议:Internet将消息从一个主机传递到另一个主机使用的协议称为网间协议,这是Internet网络协议。网间协议负责将消息发送到指定接收主机,可以适用广域网或局域网,高速网或低速网,无线网或有线网等几乎所有类型的网络通信技术。 2. TCP传输控制协议:TCP是一种可靠的面向连接的传送服务,消息在传递时被分解成一个个的小包,传输控制协议负责收集这些信息包
3、,并将其按适当的次序发送,在接收端收到后再将其正确地还原。传输控制协议处理了IP协议中没有处理的通信问题,向应用程序提供可靠的通信连接,能够自动适应网络的变化,保证数据包在传送中的正确无误。 3. UDP用户数据包协议:它和TCP一样位于传输层,和IP协议配合使用,实现的是不可靠的、无连接的数据报服务,在传输数据时省去包头,但它不能提供数据包的重传。常用于客户/服务器模式中,省去建立连接和拆除连接的开销。,一、Java网络编程概述,Java语言关于网络资源的编程主要体现在三个方面:一是在Applet小程序中建立同其他URL的连接,二是对服务器上的文件进行操作,三是建立网络通讯协议。Java语言
4、为方便网络编程设计了许多有关的类,如URL类、URLconnection类以及网络通讯的Socket和ServerSocket类。 Java语言中网络编程可在三个层次上进行,一是URL层次,即最高级层次。它利用URL直接进行Internet上的资源访问和数据传输。二是Socket层次,即传统网络编程经常采用的方式,它通过在Client/Server(客户机/服务器)结构的应用程序之间建立Socket套接字连接,然后在连接之上进行数据通信,它是一种经常采用的通信模式。三是Datagram数据流层次,即最低级层次,它是使用用户数据报协议(UDP)的通信方式。,二、URL编程,URL类 1. URL
5、 URL(Uniform Resource Locator)统一资源定位器用于表示网络资源的地址。网络上的每个资源都有它固定的地址,使用时需要首先知道它的URL,并通过URL和URLConnection类中的方法获取网络资源。 URL的结构分为两部分:传输协议和资源名称,中间用:/分隔开,传输协议说明访问资源时使用的网络协议。资源名称的格式与所使用的传输协议有关,通常由以下结构格式中一个或几个组成:(1)主机名称(host name):资源所在主机的名称。(2)文件名(filename):资源在机器上的完整名字(包括文件的完整路径名)。(3)端口号(port number):连接时所使用的服务
6、器端口号。(4)参考点(reference):资源中的特定位置,用来标识一个文件中特定的偏移位置。,二、URL编程,2. J包中URL类定义 URL类中定义了许多简单实用的方法,利用它们可以进行一些有关URL的操作。如获取URL属性信息的有getProtocol()方法(获取URL中的传输协议,返回值为String类型)、getHost()方法(获取URL中的主机名称,返回值为String类型)、getPort()方法(获取URL中的端口号,返回值为int类型)、getFile()方法(获取资源的文件名,返回值为String类型)、getRef()方法(获取URL中的参考点,返回值为Strin
7、g类型)以及操作URL资源的openStream()方法(与服务器上的文件建立一个输入流的连接)、toString()方法(将URL的内容转成字符串)、same File()方法(用于比较判断两个URL的数据是否相同)等。,二、URL编程,3. 创建URL对象(1)new URL(url字符串) (2)new URL(协议,主机名,文件名或路径) (3)new URL(协议,主机名,端口号,文件名或路径) (4)new URL(基准url,文件名或路径),二、URL编程,4. J包中URLConnection类 Java语言的.URLConnection类和.URL类一样,它使得编程者能方便地
8、利用URL在Internet上进行网络通信。 URLConnection类中包含了更丰富的方法,可以对服务器上的文件进行更多的处理。URLConnection类的构造方法是URLConnection(URL),可以构造一个对指定URL的连接对象。用URLConnection的构造方法来构造URLConnection类时,并未建立与指定URL的连接,所以还需要使用URLConnection类中的connect()方法建立连接。 在URL类中定义了openConnection()方法,使用URL类中的openConnection方法创建URLConnection对象时,已建立了网络连接,所以不需要
9、再使用connect()方法建立连接了。,二、URL编程,5. AppletContext接口类 AppletContext类是一个接口类,Applet小程序通过AppletContext接口与环境进行通讯。利用这个类可以从运行Applet小程序的环境中获取信息,而这个环境一般是指浏览器。AppletContext类没有构造方法,但是可以通过Applet类中的getAppletContext()方法获取AppletContext接口,使用Applet类中showStatus()方法可以在浏览器的状态条中显示提示信息,使用showDocument()方法可以通知浏览器在指定窗口中显示另一个URL
10、的内容。,二、URL编程,URL获取网络信息与资源 Java语言在网络上读取网络数据内容时,完全可以按照标准文件输入流方式来处理,只不过创建的对象是一个URL类型的对象。读取网络数据可分为如下几个步骤:(1)创建一个URL类型的对象。(2)使用Java语言中相应的方法获取创建对象所代表的信息和资源。(3)每隔一定时间读取网络站点提供的最新数据(更新)。 一个URL对象代表了某一个网络资源,当一个URL对象建立后,可以通过URL类提供的几个主要方法来访问它指向的资源(获取网站属性和URL内容)。例如使用URL类的getHost()等方法可以获取主机信息、使用URL类的getContent()方法
11、直接获取URL内容、使用URL类的openConnection()方法得到与URL的URLConnection连接、使用openStream()方法获得对应的InputStream输入流对象等,二、URL编程,二、URL编程,1. 获取网络属性信息 在Java语言中,通过URL类的getFile()、getHost()、getPort()、getProtocol()、getRef()等方法可以获取一个网站的属性信息。2. 创建输入流(InputStream)对象 java.io包中InputStream输入流类是一抽象类,作为其他输入流类的基类,对应着读取字节流信息的基本接口,提供了其所有子类
12、都能调用的方法。,二、URL编程,URL编程实例 1. 读取网络文本文件实例 对于网络文本文件的读取可以作为网络输入流的形式利用URL类的openStream()方法打开,并获得对应的InputStream类的对象,将Input-Stream对象再转化为DatalnputStream类的对象,通过DatalnputStream类中的方法完成读取对象中的数据内容。例数据流方式读取网络文本文件内容import java.io.*;import .*;public class ReadURL public ReadURL() public static void main(String args)
13、URL url = null; InputStream in = null; try System.out.println(Creating URL.); url = new URL(args0);/args0=http:/ System.out.println(Opening Stream.); in = url.openStream();,二、URL编程,DataInputStream buffer = new DataInputStream(in); System.out.println(Reading data.);String lineOfData;while(lineOfData
14、= buffer.readLine()!=null) System.out.println(LINE:+lineOfData); catch(MalformedURLException e) System.out.println(Bad URL);catch(IOException e)System.out.println(IO Error+e.getMessage();finallyif( in != null )tryin.close();System.out.println(Stream Closed.);catch (IOException e)System.exit(0);,二、UR
15、L编程,2. 从网络中读取图像实例 Java语言程序可以直接从网络站点上获取图像资料并显示出来。从网络站点上获取图像资料时,需要创建用于网络操作的Image类型的对象,一旦获得Image类型的对象,便可对图像资料进行任何有关图像类型的操作。例 从网络中读取图像import .*;import java.io.*;import java.awt.*;import java.awt.image.*;import java.awt.event.*;public class getURLImage extends Frame private Image img; public void paint(G
16、raphics g)g.drawImage(img,20,20,this); public void processWindowEvent(WindowEvent e) super.processWindowEvent(e); if(e.getID()=WindowEvent.WINDOW_CLOSING)System.exit(0);,二、URL编程,public static void main(String args)throws MalformedURLException,IOException if(args.length != 1) System.out.println(Usage
17、:java URLTest);System.exit(-1); URL url = new URL(args0); getURLImage urlt = new getURLImage();urlt.img = urlt.createImage(ImageProducer)url.getContent();urlt.enableEvents(AWTEvent.WINDOW_EVENT_MASK);urlt.setSize(300,300); urlt.setVisible(true);,二、URL编程,3. 动态获取网络资源实例 Java语言动态性的一个实例体现在它可以动态地获取网络上的各种资
18、源,其实现方法是编制线程程序,每隔一定的时间自动地到指定的网络站点上读取最新的内容。例 在Applet小程序中加入一个线程,该线程每隔5秒读取一次网络上的文件内容。 import java.io.*;import .*;import java.awt.*;import java.applet.*;public class dynashow extends java.applet.Applet implements Runnable Thread dthread; URL fileurl; TextArea showarea = new TextArea(Wait for a while.,5,
19、100); public void init()String url = http:/localhost/postinfo.html; try fileurl = new URL(url); catch(MalformedURLException e)System.out.println(Cant open the URL); add(showarea); ,二、URL编程,public void start()if(dthread = null)dthread = new Thread(this); dthread.start(); public void stop()if (dthread
20、 != null)dthread.stop(); dthread = null; public void run() InputStream filecon = null; DataInputStream filedata = null; String fileline;while(true) tryfilecon = fileur.openStream(); filedata = new DataInputStream(filecon); while(fileline = filedata.readLine()!= null)showarea.setText(fileline+n); cat
21、ch(IOException e)System.out.println(IO Error+e.getMessage();try dthread.sleep(5000); catch (InterruptedException e) repaint();,三、Socket编程,Socket通信的一般结构 套接字是一种基于网络进程通讯的接口即一种软件形式的抽象表述,用于表示两台机器之间在一个连接上的两个终端。即针对一个连接,每台机器上都有一个套接字,它们之间有一条虚拟线缆,线缆的每一端都插入到一个套接字里。机器之间连接的物理硬件以及使用什么电缆连接都是完全未知的,套接字抽象描述的基本宗旨是尽可能地
22、屏蔽硬件连接的细节。Java语言中,一个套接字由主机号、端口号和协议名三部分主要内容组成。,三、Socket编程,在使用套接字通信过程中主动发起通信的一方称为客户机,接受请求进行通信的一方称为服务器。通过套接字建立连接的过程分为以下三个步骤:(1)服务器建立守护进程,负责监听每个端口是否要求进行通信。(2)客户创建一个Socket对象,包括连接的主机号和端口号,指定使用的通信协议,通过发出通信请求,与服务器试图建立连接。(3)服务器监听到客户机的请求,创建一个Socket接受连接对象,与客户机进行通信。 在Java语言中,通过创建套接字可以建立与其他机器的连接并创建套接字InputStream
23、和OutputStream流对象,套接字输入/输出流完全可以将连接作为一个I/0流对象来对待。,三、Socket编程,三、Socket编程,TCP Socket编程1. Socket类 J包中的Socket类用在客户端,在客户端通过构造一个Socket类来建立与服务器的连接。Socket类的连接可以是数据流连接,也可以是数据报连接,它取决于构造Socket类时使用的构造方法。一般使用数据流连接,数据流连接的优点是所有的数据都能准确、有序地送到接收方,缺点是速度较慢。 Socket类中有四种构造方法。Socket(String,int)构造一个连接指定主机、指定端口Socket的类。Socket
24、(String,int,boolean)构造一个连接指定主机、指定端口的Socket类,boolean类型的参数用来设置是数据流Socket类还是数据报Socket类。Socket(InetAddress,int)构造一个连接指定Internet地址、指定端口的Socket类。Socket(InetAddress,int,boolean)构造一个连接指定Internet地址、指定端口的Socket类,boolean类型的参数用来设置是数据流Socket类还是数据报Socket类。,三、Socket编程,2. ServerSocket类 ServerSocket类用在服务器端,它监听和响应客户端
25、的连接请求,并接收客户端发送的数据。ServerSocket类的主要任务是在服务器端耐心地等候其他机器同它连接,一旦客户端程序申请建立一个套接字连接,ServerSocket类就会通过accept()方法返回一个对应的服务器端套接字对象,以便进行直接通信。从两台计算机连接成功时起,服务器端与客户端就得到了一个真正的连接,此时利用Socket类中getlnputStream()以及getOutputStream()方法从每端的套接字产生对应的InputStream和OutputStream对象,并将套接字数据流封装到缓冲区内以便进行两台机器之间的数据通讯。,三、Socket编程,ServerSo
26、cket类的构造方法有两种。 ServerSocket(int)是在指定端口上构造一个 ServerSocket类,ServerSocket(int,int)是在指定端口上构造一个ServerSocket类,并进入监听状态,第二个int类型的参数是监听时间长度。创建一个ServerSocket类时,只需为其赋予一个端口编号,不必把一个IP地址分配给它,因为它已经在自己代表的那台机器上了。但在创建一个Socket类时,却需要同时赋予IP地址以及要连接的端口编号。,三、Socket编程,Java语言通过Socket类和ServerSocket类建立两台计算机的连接,它们的连接过程首先是在服务器端构
27、造一个ServerSocket类,在指定端口上进行监听,这将使监听线程处于等待状态。然后在客户端构造Socket类,与服务器上的指定端口进行连接。服务器监听到连接请求后,就可在两者之间建立连接,建立连接的具体细节对客户端是透明的。在建立连接之后,就可以建立相应的输入/输出流,两端通过流来进行通讯。,三、Socket编程,在服务器端ServerSocket类会创建一个监听用的监听套接字。这个套接字会监听进入的连接,然后利用accept()方法返回一个已建立套接字,以及同时返回已建立连接的客户端IP地址和端口号。在服务器端出现的两个套接字(监听和已建立)都与相同的服务器套接字关联在一起。监听套接字
28、只能接收新的连接请求,不能接收实际的数据包,所以监听套接字只是物理意义的连接。 在服务器上创建监听对象及产生Socket对象并建立相应的套接字输入/输出流的程序是通过ServerSocket类的accept()方法监听服务器的8080端口是否有客户端请求连接,如果有客户端请求并连接成功,则创建套接字输入/输出流对象,同客户端进行数据交换。,三、Socket编程,UDP Socket编程 数据报是以UDP(User Datagram Protocol用户数据报协议)为通信协议的一种通信方式,它为两台计算机之间提供一种非可靠的无连接投递报文的通信服务,由于这种通信方式不建立连接,所以它不能保证所有
29、的数据都能准确、有序地送到目的地,它允许重传那些由于各种原因半路地丢失的数据。数据报的优点是通讯速度比较快,因此数据报服务一般用于传送非关键性的数据。,三、Socket编程,在客户机和服务器之间传递信息有两种方式,一种是建立连接的通信方式,它首先需要建立连接,然后再传递数据,所有的数据是以包(packet)的形式按照一定的顺序发送和接收的,最后关闭连接,这一通信过程是由管道(channel)来保证的。另一种是无连接的通信方式,这种方式不建立连接,它是在客户机和服务器之间利用数据报来发送和接收相互独立的数据包,这一通信过程没有建立一个专门的通信管道,所以它在网络线路无效的情况下数据包也会被发送出
30、去。,三、Socket编程,在管道通信中,数据包中不包含有关包的源和目的信息,这些信息由建立的通信管道负责指明。而在无连接通信(数据报方式)中,所有的包都需要包含有该包的完整的源和目标信息,以便指明该数据包的走向。在网络通信中,有时是不需要建立通信管道的。如时钟服务,服务器向客户机发送当前的时间信息,如果客户机丢失了一个包或者包没有按指定顺序到达,服务器再重新发送一次,丢失的时间信息包已经没有意义了,因为客户机能够计算出数据包的顺序,并且总是利用最新数据包中的时间信息,在这种情况下建立连接通信服务是不必要的。当在网络中数据传输的速度显得更重要一些时,使用UDP协议通信更为合适。例如声音信号的传
31、输,有少量数据包的丢失对声音的整体效果没有太大的影响。大多数互联网游戏也是采用UDP协议通信,因为网络通信的快慢是游戏是否流畅的决定性因素。,三、Socket编程,Java利用数据报模式在网络上发送和接收数据包需要使用类库中的Datagram Socket类和DatagramPacket类。DatagramSocket类用于收发数据包,而DatagramPacket类则包含了具体的数据信息。 DatagramPacket类是进行数据报通信的基础,它包含了需要传送的数据、数据报的长度、IP地址和端口号等。如果需要创建一个准备传出数据的DatagramPacket类,那么需要知道一个准确的因特网地
32、址和端口号。 DatagramPacket(byte buf,int length)构造方法为构造一个用于接收数据报的Datagram Packet类,byte类型的参数是接收数据报的缓冲区,int类型的参数是接收数据报中的字节数(数据包长度)。 public DatagramPacket(byte口buf, int length, InetAddress address, int port)构造方法为构造一个用于发送数据的DatagramPacket类,byte类型参数是发送数据的缓冲区,int类型参数是发送的字节数,InetAddress类型参数是接收机器的Internet地址,最后一个参
33、数是接收的端口号。,三、Socket编程,DatagramSocket类是用来发送数据报的套接字,它通过套接字方式进行数据报通信。DatagramSocket()构造方法是构造一个用于发送数据包的DatagramSocket类。Datagram Socket(int)构造方法是构造一个用于接收数据包的DatagramSocket类,当构造完成Datagram Socket类后,就可以发送和接收数据包了。 使用DatagramSocket类和DatagramPacket类来编写发送端和接收端程序可以实现数据报的发送和接收。在使用数据报通信模式准备接收一个数据报时,接收端只需要提供一个缓冲区,以便
34、安置接收到的数据,缓冲区的最大容量仅受限于允许的数据报包大小,一般小于64KB。数据包抵达时,通过DatagramSocket类作为信息源的因特网地址以及端口编号会自动得到初始化。在发出一个数据包时,DatagramPacket类不仅需要包含正式的数据,也需要包含因特网地址以及端口号,以决定数据包到达的目的地。,三、Socket编程,使用数据报通信时,在接收端和发送端需要创建并运行各自的Java语言程序,首先需要在接收端建立一个接收的Data-gramSocket类,在指定端口上监听并构造一个Datagram Packet类指定接收的数据缓冲区。在发送端需要构造Datagram-Packet类
35、,指定要发送的数据、数据长度、接收主机地址及端口号,然后使用DatagramSocket类中的send()方法来完成发送数据报。在接收端接收到数据报后,将数据保存到缓冲区,同时保存发送端的主机地址和端口号。接收完毕后再将接收到的数据报返回给发送端,并附加上接收端接收缓冲区地址、缓冲区长度、发送端地址和端口号等信息,当完成一个数据包的接收之后,接收端等待接收下一个新的数据。,三、Socket编程,例如接收端程序可为: byte inbuffer = new byte1024; /定义接收缓冲区 DatagramPacket inpacket = new DatagramPacket(inbuff
36、er,inbuffer,length); DatagramSocket inSocket = new DatagramSocket(8080); inSocket.receive(inpacket);/监听数据报 String s = new String(inbuffer,0,0,inpacket.getlength);/将接收数据存入字符串s发送端程序可为: DatagramPacket outpacket = new DatagramPacket(message,200,202.112.88.31,8080); DatagramSocket outSocket = new Datagra
37、mSocket(); outSocket.send(outpacket); /发送数据报,三、Socket编程,Socket编程实例 使用Java语言进行网络编程最大的困难是测试网络程序的正确性,因为需要两台联接到Internet网络上的TCP/IP计算机,一台用于运行服务器程序,一台用于运行客户机程序。当不具备这些条件时,Java语言提供了一种回调(loopback)机制来完成网络程序的测试,其方式是服务器和客户机同属于一台计算机并共同使用一个IP地址,它使服务器和客户机形成一个封闭环。即可以在单机上运行Web服务软件以及使用Web浏览器来模拟网络编程,从而检验编制的Java语言程序是否正确
38、。,三、Socket编程,在没有网络环境的前提下测试网络程序首先需要建立一个特殊的IP地址,如localhost,使用该IP地址来满足非网络环境中的测试要求。在Java语言中产生这个地址的一般方法为: InetAddress addr = InetAddress.getByName(null); 如果向getByName()传递一个null值,即默认为使用localhost地址。使用InetAddress类型可以对特定的机器进行索引,当被测试的网络程序在进行进一步的操作之前需要得到这个Internet地址。 InetAddress.getByName(localhost);或者 InetAdd
39、ress.getByName(127.0.0.1);说明:创建一个特殊IP地址是使用.InetAddress类中的getByName()、 getAllBy Name()或者getLocalHost()成员方法来完成的。使用InetAddress类中这些成员方法时,事先需要知道计算机的名称。,三、Socket编程,例客户机与服务器的通信import java.io.*;import .*;public class ClientServer public ClientServer() new Thread(new MyServer().start();new Thread(new MyClien
40、t().start(); public static void main(String args)new ClientServer();class MyServer implements Runnable public void run() ServerSocket server = null; Socket serverSocket = null;OutputStream os = null;tryserver = new ServerSocket(88,16); serverSocket = server.accept(); System.out.println(Connect on th
41、e Server side!); os= serverSocket.getOutputStream(); os.write(50); server.close();catch(IOException e)System.out.println(Caught Exception:+e);,三、Socket编程,class MyClient implements Runnable public void run() Socket clientSocket = null; InputStream is = null;try clientSocket = new Socket(InetAddress.g
42、etLocalHost(),88);is = clientSocket.getInputStream();System.out.println(Client reads:+is.read(); clientSocket.close();catch(UnknownHostException e) System.out.println(Caught Excepion:+e);catch(IOException e)System.out.println(Caught Exception:+e);,小结,端口和IP地址为网络通信提供了确定的地址标识,IP地址表示发送端的目的计算机,端口表明将数据包发送给目的计算机上的哪一个服务。套接字是网络驱动层提供给应用程序编程的接口和管理方法,用于处理数据接受与输出。Java语言访问网络资源是通过URL类来实现的,通过调用URL类的方法完成网络通信。套接字(Socket)提供网络上两台计算机之间交互通信的可靠连接,数据报为两台计算机之间提供一种快速、非可靠的无连接投递报文的通信服务。,