资源描述
,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第,11,章,Java,中的网络编程,本章导读,1.URL,类,2.,读取,URL,中的资源,3.,显示,URL,资源中的,HTML,文件,4.,处理超链接,5.InetAddress,类,6.,套接字,Socket,7.,使用多线程处理套接字连接,8.UDP,数据报,9.,广播数据包,11.1 URL,类,包中的,URL,类是对统一资源定位符(,Uniform Resource Locator,)的抽象,使用,URL,创建对象的应用程序称作客户端程序,一个,URL,对象存放着一个具体的资源的引用,表明客户要访问这个,URL,中的资源,利用,URL,对象可以获取,URL,中的资源。一个,URL,对象通常包含最基本的三部分信息:协议、地址、资源。协议必须是,URL,对象所在的,Java,虚拟机支持的协议,许多协议并不为我们所常用,而常用的,Http,、,Ftp,、,file,协议都是虚拟机支持的协议;地址必须是能连接的有效,IP,地址或域名;资源可以是主机上的任何一个文件。,1,URL,的构造方法,public URL(String spec)throws MalformedURLException,该构造方法使用字符串初始化一个,URL,对象,例如,try,url=new URL();,catch(MalformedURLException e),System.out.println(Bad URL:+url);,该,URL,对象使用的协议是“,Http,”,协议,即用户按着这种协议和指定的服务器通信,该,URL,对象包含的地址是“,”,,所包含的资源是默认的资源(主页)。,public URL(String protocol,String host,String file)throws MalformedURLException,该构造方法构造的,URL,对象的协议、地址和资源分别由参数,protocol,、,host,和,file,指定,返回,11.2,读取,URL,中的资源,URL,对象调用,InputStream openStream(),方法可以返回一个输入流,该输入流指向,URL,对象所包含的资源。通过该输入流可以将服务器上的资源信息读入到客户端。,下面的,例子,1,在一个文本框中输入网址,然后点击确定按钮读取服务器上的资源,由于网络速度或其它的因素,,URL,资源的读取可能会引起堵塞,因此,程序需在一个线程中读取,URL,资源,以免堵塞主线程。,返回,11.3,显示,URL,资源中的,html,文件,在上面的例子,1,中,我们可以将,的主页的内容显示在文本区中,但是,有时候我们想看到网页的运行效果。,Javax.swing,包中的,JEditorPane,类可以解释执行,html,文件,也就是说,如果你把,html,文件读入到,JEditorPane,,该,html,文件就会被解释执行,,显示在,JEditorPane,中,这样程序就看到了网页,的运行效果。,可以使用,JEditorPane,类的构造方法:,public JEditorPane(),public JEditorPane(URL initialPage)throws IOException,public JEditorPane(String url)throws IOException,构造,JEditorPane,对象,后两个构造方法使用参数,initialPage,或,url,指定该对象最初显示的,URL,中的资源。,JEditorPane,对象调用,public void setPage(URL page)throws IOException,法可以显示新的,URL,中的资源。,在下面的,例子,2,中,我们用,JEditorPane,对象显示网页。,返回,11.4,处理超链接,当,JEditorPane,对象调用,setEditable,方法将编辑属性设为,false,时,不仅可以显示网页的运行效果,而且用户如果单击网页中超链接还可以使得,JEditorPane,对象触发,HyperlinkEvent,事件。程序可以通过处理,HyperlinkEvent,事件,来显示新的,URL,资源。,JEditorPane,对象调用,addHyperlinkListener(HyperlinkListener listener),获得监视器。监视器需实现,HyperlinkListener,接口,该接口中的方法是:,void hyperlinkUpdate(HyperlinkEvent e),在下面的,例子,中,当单击超链接时,,JEditorPane,对象 将显示超链接所链接的网页。,返回,11.5 InetAdress,类,我们已经知道,Internet,上的主机有两种方式表示地址:,(,1,)域名,例如,,(,2,),IP,地址,例如,,202.108.35.210,包中的,InetAddress,类对象含有一个,Internet,主机地址的域名和,IP,地址:,s);,将一个域名或,IP,地址传递给该方法的参数,s,,获得一个,InetAddress,对象,该对象含有主机地址的域名和,IP,地 址,该对象用如下格式表示它包含的信息:,运行结果:,String getHostName(),取,InetAddress,对象所 含的域名。,public String getHostAddress(),获取,InetAddress,对象所含的,IP,地址。,2,获取本地机的地址,我们可以使用,InetAddress,类的静态方法:,getLocalHost();,获得一个,InetAddress,对象,该对象含有本地机的域名和,IP,地址。,返回,11.6,套接字,Socket,IP,地址标识,Internet,上的计算机,端口号标识正在计算机上运行的进程(程序)。端口号与,IP,地址的组合得出一个网络套接字。端口号被规定为一个,16,位的整数,065535,。其中,,01023,被预先定义的服务通信占用(如,telnet,占用端口,23,,,http,占用端口,80,等)。除非我们需要访问这些特定服务,否则,就应该使用,102465535,这些端口中的某一个进行通信,以免发生端口冲突。,1,套接字连接,所谓套接字连接就是客户端的套接字对象和服务器端的套接字对象通过输入、输出流连接在一起,现在我们分三个步骤来说明套接字连接的基本模式。,(,1,)服务器建立,ServerSocket,对象,ServerSocket,对象负责等待客户端请求建立套接字连接,类似邮局某个窗口中的业务员。也就是说,服务器必须事先建立一个等待客户请求建立套接字连接的,ServerSocket,对象。,ServerSocket,的构造方法是:,ServerSocket(int port),当建立服务器套接字时可能发生,IOException,异常,因此要象下面那样建立接收客户的服务器套接字。,try ,ServerSocket waitSocketConnection=new ServerSocket(1880);,catch(IOException e),当服务器的,ServerSocket,对象,waitSocketConnection,建立后,就可以使用方法,accept(),接受客户的套接字连接请求,代码如下所示:,waitSocketConnection.accept();,接收客户的套接字也可能发生,IOException,异常,因此要象下面那样建立接受客户的套接字。,try,Socket socketAtServer=waitSocketConnection.accept();,catch(IOException e),所谓“接收”客户的套接字请求,就是,accept(),方法会返回一个,Socket,对象:,socketAtServer,,称作服务器端的套接字对象。,Socket socketAtServer=waitSocketConnection.accept();,System.out.println(,“,ok,”,),catch(IOException e),(,2,)客户端创建,Socke,对象。,客户端程序可以使用,Socket,类创建对象,,Socket,的构,方法是:,Socket(String host,int port),参数,host,是服务器的,IP,地址,,port,是一个端口号。,也可以使用,Socket,类不带参数的构造方法,public Socket(),创建一个套接字对象,该对象不请求任何连接。该对象再调用,public void connect(SocketAddress endpoint)throws IOException,请求和参数,SocketAddress,指定地址的套接字建立连接。为了使用,connect,方法,可以使用,SocketAddress,的子类:,InetSocketAddress,创建一个对象,,InetSocketAddress,的构造方法是:,public InetSocketAddress(InetAddress addr,int port),创建,Socket,对象可能,发生,IOException,异常,因此要象 下面那样建立到服务器的套接字连接,try,Socket socketAtClient=new Socket(,“,192.168.0.78,”,1880);,catch(IOException e),客户端建立,socketAtClient,对象的过程就是向服务器发出套接字连接请求,如果服务器端相应的端口上有,ServerSocket,对象正在使用,accept,方法等待客户,那么双方的套接字对象,socketAtClient,和,socketAtServer,就都诞生了。,(,3,)流连接,客户端和服务器端的套接字对象诞生以后,还必须进 行输入、输出流的连接。,服务器端的这个,Socket,对象,socketAtServer,使用方法,getOutputStream(),获得的输出流将指向客户端,Socket,对象,socketAtClient,使用方法,getInputStream(),获得的那个输入流;同样,服务器端的这个,Socket,对象,ocketAtServer,使用方法,getInputStream(),获得的输入流将指向客户端,Socket,对象,socketAtClient,使用方法,getOutputStream(),获得的那个输出流。因此,当服务器向这个输出流写入信息时,客户端通过相应的输入流就能读取,反之亦然。,图,11.3,套接字连接示意图,客户端,Socket,输入流,输出流,服务器端,Socket,输出流,输入流,连接,连接,连接建立后,服务器端的套接字对象调用,getInetAddress(),方法可以获取一个,InetAddess,对象,该对象含有客户端的,IP,地址和域名,同样,客户端的套接字对象调用,getInetAddress(),方法可以获取一个,InetAddess,对象,该对象含有服务器端的,IP,地址和域名。,套接字调用,close(),可以关闭双方的套接字连接,只要一方关闭连接,就会导致对方发生,IOException,异常。,下面我们通过一个简单的例子说明上面讲的概念。,在,例子,5,中,客户端向服务器发出,ASCII,表的顺序值:,1127,;服务器接受这些数据,并将顺序值对应的字符返回给客户。你首先将例子,5,中服务器端的,Server.java,编译通过,并运行起来,等待客户请求连接。然后运行客户端程序。,返回,11.7,使用多线程处理套接字连接,套接字连接中涉及到输入流和输出流操作,客户或服务器读取数据可能会引起堵塞,我们应把读取数据放在一个单独的线程中去进行。另外,服务器端收到一个客户的套接字后,就应该启动一个专门为该客户服务的线程。,我们用学过的组件,设计一个略微复杂的套接字连接。,在下面的,例子,6,中,客户输入一个一元二次方程的系数并发送给服务器,服务器把计算出的方程的实根返回 给客户。因此你可以将计算量大的工作放在服务器端,客户负责计算量小的工作,实现客户,-,服务器交互计算,来完成某项任务。,返回,11.8 UDP,数据报,基于,UDP,通信的基本模式是,(,1,)将数据打包,称为数据包(好比将信件装入信封一样),然后将数据包发往目的地。,(,2,)接受别人发来的数据包(好比接收信封一样),然后查看数据包中的内容。,1,发送数据,(,1,)创建,DatagramPacket,对象,首先用,DatagramPacket,类将数据打包,即用,DatagramPacket,类创建一个对象,称为数据包,。,返回,用,DatagramPacket,的以下两个构造方法创建待发送的数据包:,DatagramPacket(byte data,int length,InetAddtress address,int port),DatagramPack(byte data,int offset,int length,InetAddtress address,int port),使用构造方法创建的数据包对象具有下列两个性质:,含有,data,数组指定的数据。,该数据包将发送到地址是,address,、端口号是,port,的主机上。,我们称,address,是它的目标地址、,port,是这个数据包的目标端口号。其中,第,2,个构造方法创建的数据包对象含有数组,data,从,offset,开始指定长度的数据。,例如:,byte data=,近来好吗,.getByte();,InetAddtress address=InetAddtress.getName();,DatagramPacket data_pack=new DatagramPacket(data,data.length,address,980);,(2),发送数据,然后用,DatagramSocket,类的不带参数的构造方法:,DatagramSocket(),创建一个对象,该对象负责发送数据包。例如,,DatagramSocket mail_out=new DatagramSocket();,mail_out.send(data_pack);,2,接收数据,DatagramSocket,类另一个构造方法:,DatagramSocket(int port),创建一个对象,其中的参数必须和待接收的数据包的端口号相同。例如,如果发送方发送的数据包的端口号是,5666,:,DatagramSocket mail_in=new DatagramSocket(5666);,该对象,mail_in,使用方法,receive(DatagramPacket pack,接受数据包。该方法有一个数据包参数,pack,,方法,receive,把收到的数据包传递给该参数。因,此我们必须预备一个数据包以便收取数据包。这时需使用,DatagramPack,类的另外一个构造方法:,DatagramPack(byte,data,int length),创建一个数据包,用于接收数据包,例如:,byte data=new byte100;int length=90;,DatagramPacket pack=new,DatagramPacket(data,length);,mail_in.receive(pack);,该数据包,pack,将接收长度是,length,的数据放入,data,。,在下面的,例子,7,中两个主机(可用本地机模拟)互相发送和接收数据包。,返回,11.9,广播数据包,广播数据包类似于电台广播,进行广播的电台需在指定的波段和频率上广播信息,接收者只有将收音机调到指定的波段、频率上才能收听到广播的内容。,广播数据包涉及到地址和端口。我们知道,,Internet,的地址是,a.b.c.d,的形式。该地址的一部分代表用户自己主机,而另一部分代表用户所在的网络。当,a,小于,128,,那么,b.c.d,就用来表示主机,这类地址称做,A,类地址。如果,a,大于等于,128,并且小于,192,,则,a.b,表示网络地址,而,c.d,表示主机地址,这类地址称做,B,类地址。如果,a,大于等于,192,,则网络地址是,a.b.c,,,d,表示主机地址,这类地址称做,C,类地址。,224.0.0.0,与,239.255.255.255,之间的地址称做,D,类地址,,D,类地址并不代表某个特定主机的位置,一,个具有,A,、,B,或,C,类地址的主机要广播数据或接收广播,都必须加入到同一个,D,类地址。一个,D,类地址也称做一个组播地址,加入到同一个组播地址的主机可以在某个端口上广播信息,也可以在某个端口号上接收信息。,准备广播或接收的主机需经过下列步骤:,1,1.,设置组播地址,使用,InetAddress,类创建组播组地址,例如:,InetAddress group=InetAddress.getByName(239.255.8.0);,2,创建多点广播套接字,使用,MulticastSocket,类创建一个,多点广播套接字对象。,MulticastSocket,的构造方法:,public MulticastSocket(int port)throws IOException,创建的多点广播套接字可以在参数指定的端口上广播。,3,设置广播的范围,准备广播的主机必须让多点广播套接字(,MulticastSocket,)对象,调用,public void setTimeToLive(int ttl)throws IOException,4,加入组播组,准备广播或接收的主机必须让多点广播套接字(,MulticastSocket,)对象,调用,public void joinGroup(InetAddress mcastaddr)throws IOException,方法加入组播组。,多点广播套接字(,MulticastSocket,)对象,调用,public void leaveGroup(InetAddress mcastaddr)throws IOException,方法可以离开已经加入的组播组。,5,广播数据和接收数据,进行广播的主机可以让多点广播套接字(,MulticastSocket,)对象,调用,public void send(DatagramPacket p)throws IOException,将参数,p,指定的数据包广播到组播组中的其它主机。,接收广播的主机可以让多点广播套接字(,MulticastSocket,)对象,调用,public void receive(DatagramPacket p)throws IOException,在下面的例子中,一个主机不断地重复广播奥运会新 闻,加入到同一组的主机都可以随时接收广播的信息。接收者将正在接收的信息放入一个文本区,把已接收到的全部信息放入另一个文本区。,(,1,),广播数据包的主机,(2),接收数据包的主机,返回,
展开阅读全文