JAVA中的网络编程
- URL类
- 读取URL中的资源
- 显示URL资源中的HTML文件
- 处理超链接
- InetAddress类
- 套接字Socket
- 使用多线程处理套接字连接
Internet是计算机最重要的应用领域之一,许多与它有关的新技术不断出现,而Java首当其中,Java在网络方面的重要性已是无可争议的了。介绍4个总要的类URL、Socket、InetAddress和DatagramSocket,讲述它们在网络中的重要作用。
Internet上的每台计算机必须被唯一地表示出来,因此网络标准化的第一个部分就是IP地址,“IP”代表Internet Protocol。IP地址用于标识连接到Internet的计算机的数字地址,IP地址是由32位二进制数组成的,如202.199.28.6。 没有IP地址就不能区分连在Internet上不同的计算机。Internet上的主机有两种方式表示地址:“域名”和“IP”,如域名"www.tsinghua.edu.cn”和IP”202.108.35.210” 是一个主机的两种表示法。域名容易记忆,在连接网络时输入一个主机的域名后,域名服务器(DNS)负责将域名转化成IP地址,这样我们才能和主机建立连接。
如果IP地址唯一标识了Internet上的计算机,则URL标识了计算机上的资源。更具体地说,URL(Uniform Resource Location,统一资源定位器)充当一个指针,指向Web上的网页、二进制文件以及其他信息对象。当读者手工输入“如 http://www.tsinghua.edu.cn/hotlink.html ”的网址时,实际上就提供了该站点主要的URL。
一个URL通常包含一些重要的信息,如“http://www.dlrin.edu.cn/hotlink/html ” 包含了如下信息:
- http---超文本传输协议(HTTP)。
- dlrin.edu.cn--存储资源的计算机的域名地址。
- hotlink.html--资源。
客户端-服务器体系结构的基本含义就是,客户端需要某些类型的信息,而服务器提供客户端所需要的信息。客户端需要连接到服务器上,并向服务器请求信息,服务器则向客户端发送信息,两者按照协议协同工作,各得其所。
URL类
java.net包中的URL类是对URL的抽象,是用URL创建对象的应用程序称为客户端程序,一个URL对象存放着一个具体的资源的引用,表明客户要访问这个URL中的资源,利用URL对象可以获取URL中的资源。一个URL对象通常包含最基本的三部分信息:协议、地址、资源。协议必须是URL对象所在的Java虚拟机支持的协议,许多协议并不为我们所常用,而常用的HTTP、FTP、FILE协议都是Java虚拟机支持的协议。地址必须是能连接的有效IP地址或域名。资源可以是主机上的任何文件。
URL的构造方法如下:
- public URL(String spec) throws MalformedURLException 使用字符串初始化一个URL对象。例如
try{ url=new Url(“http://yahoo.con.cn”); }catch(MalformedURLException e){ System.out.println(“Bad URL:”+url); }该URL对象使用的协议时HTTP,即用户按照这种协议与指定的服务器通信,该URL对象包含的地址是“yahoocom.cn”,所包含的资源是默认的资源(主页)。
- public URL(String protocol,String host,String file) throws MalformedURLException 构造的URL对象的协议、地址和资源分别由参数protocal、host和file指定。
读取URL中的资源
URL对象调用
InputStream openStream()方法可以返回一个输入流,该输入流指向URL对象所包含的资源。通过该输入流可以将服务器上的资源信息读入到客户端。
显示URL资源中的HTML文件
在上面,将http://www.yahoo.com.cn的主页的内容显示在文本区中,但是我们想看到网页的��行效果,则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中的资源。
处理超链接
当JEditorPane对象调用setEditable()方法就编辑属性设为false时,不仅可以显示网页的运行效果,而且用户如果单击网页中的链接,还可以使得JEditorPane对象触发HyperlinkEvent事件。程序可以通过处理HyperlinkEvent事件来显示新的URL资源。
JEditorPane对象调用
addHyperlinkListener(HyperlinkListener listener) 方法获得监视器。监视器需要实现HyperlinkListener接口,该接口中的方法如下:
void hyperlinkUpdate(HyperlinkEvent e)
InetAddress类
java.net包中的InetAddress类对象含有一个Internet主机地址的域名和IP地址。
可以使用InetAddress类的静态方法getByName(String s)将一个域名或IP地址传递给该方法的参数s,获得一个InetAddress对象。该对象含有主机地址的域名和IP地址,该对象用如下格式标示它所包含的信息。
www.sina.com/202.108.37.40
另外,InetAddress类中包含两个实例方法:
1 public String getHostName() 获取InetAddress对象所包含的域名。
2 publc String getHostAddress() 获取InetAddress对象所包含的IP地址。
可以使用InetAddress类的静态方法getLacalHost() 获得一个InetAddress对象,该对象含有本地机的域名和IP地址。
套接字Socket
IP地址标识Internet上的计算机,端口号标识正在计算机上运行的进程(程序)。端口号与IP地址的组合得出一个网络套接字(Socket)。端口号被规定为一个16位的整数0~65535。其中,0~1023被预先定义的服务通信占用(如telnet占用端口23,http占用端口80等)。除非我们需要访问这些特定服务,否则就应该使用1024~65535这些中的某一个进行通信,以免发生端口冲突。当两个程序需要通信时,它们可以通过使用Socket类建立套接字对象并连接在一起。比如,有人让你去“中山广场邮局”,你可能反问“我去做什么”,因为他没有告知你“端口”,你不知处理何种业务。他说“中山广场邮局,8号窗口”,那么你到达地址“中山广场邮局”,找到“8号”窗口,就知道8号窗口处理特快专递业务,而且必须有个先决条件,就是你到达“中山广场邮局8号窗口”时,就应该必须有一位业务员在等待客户,否则就无法建立通信业务。
所谓套接字连接,就是客户端的套接字对象和服务器端的套接字对象通过输入输出流连接在一起,现在我们分3个步骤来说明套接字连接的基本方式。
1,服务器建立ServerSocket对象。ServerSocket对象负责等待客户端请求建立套接字连接,类似邮局某个窗口中的业务员。也就是说,服务器实现建立一个等待客户请求建立套接字连接的ServerSocket对象。ServerSocket的构造方法如下:
ServerSocket(int port) port是一个端口号。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(服务器端的套接字对象) 。但是,accept()方法不会立刻返回,该方法会堵塞服务器端当前线程的执行,直到有客户请求建立套接字连接。也就是说,如果没有客户请求建立套接字连接,那么下述代码中的”System,our,println(“ok”);”总不会被执行:
try{ Socket socketAtServer=waitSocketConnection.accep();
System.out.println(“ok”);
}catch(IOException e){}
注:ServerSocket对象可以调用setSoTimeout(int timeout)方法设置超时值(单位是毫秒),timeout是一个正值。当ServerSocket对象调用accept()方法堵塞时间一旦超过timeout时,将触发SocketTimeoutException。
2,客户端创建Socket对象。客户端程序可以使用Socket类创建对象,Socket的构造方法如下:
Socket(String host,int port)
参数host是服务器的IP地址,port是一个端口号。
创建Socket对象可能发生IOException异常,因此要像下面那样建立到服务器的套接字连接:
try{
Socket socketAtClient=new Socket(“http://192.168.0.78”,1880);
}catch(IOException e){}
客户端建立socketAtClient对象的过程就是向服务器发出套接字连接的请求,如果服务器端相应的端口上有ServerSocket对象正在使用accept()方法等待客户,那么双方的套接字对象socketAtClient和socketAtServer���都诞生了。
也可以使用Socket类不带参数的构造方法
public Socket()
创建一个套接字对象,该对象不请求任何连接。该对象再调用
public void connect(SocketAddress endpoint) throws IOException
请求与参数SocketAddress指定地址的套接字建立连接。为了使用connect()方法,可以使用SocketAddress的子类InetSocketAddress创建一个对象。InetSocketAddress的构造方法如下:
public InetSocketAddress(InetAddress addr,int port)
3,流连接。客户端和服务器端的套接字对象诞生后,还必须进行输入/输出流的连接。
服务器端的这个Socket对象socketServer使用方法
getOutputStream()
获得的输出流将指向客户端Socket对象socketAtClient使用方法
getInputStream()
获得的那个输入流。同样,服务器端的这个Socket对象socketAtServer使用方法
getInputStream()
获得的输入流将指向客户端Socket对象socket对象socketAtClient使用方法
getOutputStream()
获得的那个输出流。因此,当服务器向这个输出流写入信息时,客户端通过相应的输入流就能读取,反之亦然。需要注意的是,从套接字连接中读取数据与从文件中读取数据有着很大的不同,尽管二者都是输入流。从文件中读取数据时,所有的数据都已经在文件中了。而使用套接字连接时,可能在另一端数据发送出来之前,就已经开始试着读取了,这就会堵塞本线程,直到该读取方法成功读取到信息,本线程才继续执行后续的操作。
连接建立后,服务器端的套接字对象调用getInetAddress()方法可以获取一个InetAddress对象,该对象含有客户端的IP地址和域名。同样,客户端的套接字对象调用getInetAddress()方法可以获取一个InetAddress对象,该对象含有服务器的IP地址和域名。
套接字关闭
套接字调用close()方法可以关闭双方的套接字连接,只要一方关闭连接,就会导致对方发生IOException异常
使用多线程处理套接字连接
套接字连接中涉及到输入流和输出流的操作,客户端或服务器读取数据可能会引起堵塞,我们应把读取数据放在一个单独的线程中去进行。另外,服务器收到一个客户的套接字后,就应该启动一个专门为该客户服务的线程。