第一节 网络运行机制说明
Java
用于网络操作的功能包是java.net,它包含了多个访问各种标准网络协议的类库。Java的网络访问类库分别支持以下三个层次的网络运行机制
Java
支持URL访问网络资源的机制,通过URL标识,可以直接使用http、file、ftp等多种协议,以获取远程计算机上的资源信息,方便快捷地开发internet应用程序
Java
提供对应于Socket机制的一组类,按照用户约定的通信协议,实现网络通信。这种方式更适合开发特定功能的网络通信程序
第二节 使用URL访问网络资源
Ø
什么是URL
想要访问一台网络连接到Internet的计算机,则这台计算机必须要有惟一的标识,称为IP地址(Internet Protocol),就像每家每户的住宅地址一样。IP地址是惟一标识Internet上计算机的数字地址。IP地址由32位二进制组成。如:202.199.28.6
URL
是统一资源定位符(Uniform Resource Locator)的简称,它表示Internet上某一资源的地址
通过URL,就可以访问Internet。浏览器或其他程序通过解析给定的URL就可以在网络上查找相应的文件或其他资源
URL
的基本结构由5部分组成:
<
传输协议>://<主机名>:<端口号>/<文件名>#<引用>
Ø
URL类
在java.net包中定义了URL类。声明如下:
Public final class URL extends Object implements serializable
构造方法:
public URL(String spec)
public URL(URL context, String spec)
public URL(String protocol, String host, String file)
public URL(String protocol, String host, int port, String file)
当创建URL时发生错误,系统会产生例外MalformedURLException,这是非运行时例外,必须在程序中捕获处理。
一个URL对象生成后,其属性是不能被改变的,但可以通过它给定的方法来获取这些属性:
public String getProtocol()
:获取该URL的协议名
public String getHost()
:获取该URL的主机名
public String getPort()
:获取该URL的端口号
public String getPath()
:获取该URL的文件路径
public String getFile()
:获取该URL的文件名
public String getRef()
:获取该URL在文件中的相对位置
public String getQuery()
:获取该URL的查询名
例 10.1 创建URL对象属性。
本例分别以http和file协议构造URL对象,获取URL对象属性并捕获URL异常。
程序如下:
import java.net.*;
public class URL1
{
public static void main(String args[])
{
URL url;
try
{
url = new URL("file:d:/jdk1.3/docs/api/index.html#chapt1");
info(url);
url = new URL("http","www.edu.cn","/web/myfile.html#chapt1");
info(url);
url = new URL("http//www.edu.cn");
info(url);
}
catch(MalformedURLException e)
{
System.out.println(e);
}
}
public static void info(URL url)
{
System.out.println("URL is ");
System.out.println("toString()= "+url.toString());
System.out.println("Protocol = "+url.getProtocol());
System.out.println("Host = "+url.getHost());
System.out.println("Port = "+url.getPort());
System.out.println("File = "+url.getFile());
System.out.println("Ref = "+url.getRef());
}
}
程序运行结果:
URL is
toString()= file:d:/jdk1.3/docs/api/index.html#chapt1
Protocol = file
Host =
Port = -1
File = d:/jdk1.3/docs/api/index.html
Ref = chapt1
URL is
toString()= http://www.edu.cn/web/myfile.html#chapt1
Protocol = http
Host = www.edu.cn
Port = -1
File = /web/myfile.html
Ref = chapt1
java.net.MalformedURLException: no protocol: http//www.edu.cn
Ø
针对HTTP协议的URLConnection类
URL
的方法openStream(),只能从网络上读取资源中的数据。通过URLConnection类,可以在应用程序和URL资源之间进行交互,既可以从URL中读取数据,也可以向URL中发送数据。URLConnection类表示了应用程序和URL资源之间的通信连接。
通过URLConnection对象获取的输入流和输出流,可以与现有的CGI程序进行交互
URLConnection
类的实例方法:
Ø
Public Object getContent()throws IOException
Ø
Public int getContentLength()
Ø
Public String getContentType()
Ø
Public long getDate()
Ø
Public long getLastModified()
Ø
Public InputStream getInputStream()throws IOException
例 10.3 使用URLConnection对象访问HTTP协议表示的远程文件。
本例使用URLConnection对象访问HTTPF协议表示的教育网上的index.htm文件,获取更多的文件信息。程序如下:
import java.net.*;
import java.io.*;
import java.util.Date;
public class URL3
{
public static void main(String args[])
{
String urlname = "http://www.edu.cn/index.html";
if (args.length>0)
urlname = args[0];
new URL3().display(urlname);
}
public void display(String urlname)
{
try
{
URL url = new URL(urlname);
URLConnection uc = url.openConnection();
System.out.println("
当前日期: "+new Date(uc.getDate())+
"/r/n"+"
文件类型: "+uc.getContentType()+"/r/n"+
"
修改日期: "+new Date(uc.getLastModified()));
int c, len;
len = uc.getContentLength(); //
获取文件长度
System.out.println("
文件长度: "+len);
if(len>0)
{
System.out.println("
文件内容:");
InputStream in = uc.getInputStream(); //
建立数据输入流
int i = len;
while(((c=in.read())!=-1) && (i>0))
{ //
按字节读取所有内容
System.out.print((char)c);
i--;
}
}
}
catch(MalformedURLException me)
{
System.out.println(me);
}
catch(IOException ioe)
{
System.out.println(ioe);
}
}
}
程序运行结果:
当前日期: Thu Jan 23 11:16:25 CST 2003
文件类型: text/html
修改日期: Mon Aug 20 11:17:16 CST 2001
文件长度: 90
文件内容:
<html>
<script>
window.navigate("/HomePage/jiao_yu_fu_wu/index.shtml");
</script>
</html>
第三节 Socket通信机制
在Java中,基于TCP协议实现网络通信的类有两个:在客户端的Socket类和在服务器端的ServerSocket类。
在服务器端通过指定一个用来等待的连接的端口号创建一个ServerSocket实例。
在客户端通过规定一个主机和端口号创建一个 socket实例,连到服务器上。
ServerSocket
类的accept方法使服务器处于阻塞状态,等待用户请求。
构造方法:
Ø
public Socket(String host, int port)
Ø
public Socket(InetAddress address, int port)
Ø
public Socket(String host, int port, InetAddress localAddr, int localPort)
Ø
public Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
类ServerSocket
•
public ServerSocket(int port)
•
public ServerSocket(int port, int backlog)
:支持指定数目的连接
•
public ServerSocket(int port, int backlog, InetAddress bindAddr)
•
这些方法都将抛出例外IOException,程序中需要捕获处理。
•
主要方法
•
public Socket accept()
:等待客户端的连接
•
public void close()
: 关闭Socket
•
设置/获取Socket数据
•
public InetAddress getInetAddress()
、public int getLocalPort(),…
•
public void setSoTimeout(int timeout)
,…
•
这些方法都将抛出例外SocketException,程序中需要捕获处理。
例 10.4 Socket通信的服务端程序。
本例演示Socket通信中的服务端操作,程序如下:
import java.net.*;
import java.io.*;
public class Server1 implements Runnable
{
ServerSocket server = null;
Socket clientSocket;
boolean flag = true; //
标记是否结束
Thread c; //
向客户器端发送信息的线程
BufferedReader sin;
DataOutputStream sout;
public static void main(String args[])
{
new Server1().ServerStart();
}
public void ServerStart()
{
try
{
server = new ServerSocket(5678);
System.out.println("
端口号:"+server.getLocalPort());
while(flag)
{
clientSocket = server.accept();
System.out.println("
已建立连接!");
InputStream is = clientSocket.getInputStream();
sin = new BufferedReader(new InputStreamReader(is));
OutputStream os = clientSocket.getOutputStream();
sout = new DataOutputStream(os);
c = new Thread(this);
c.start(); //
启动线程,向客户器端发送信息
String aline;
while((aline=sin.readLine())!=null)
{ //
接收客户端的数据
System.out.println(aline);
if(aline.equals("bye"))
{
flag = false;
c.interrupt(); //
线程中断
break;
}
}
sout.close(); //
关闭流
os.close();
sin.close();
is.close();
clientSocket.close(); //
关闭Socket连接
System.exit(0); //
程序运行结束
}
}
catch(Exception e)
{
System.out.println(e);
}
}
public void run()
{
while(true)
{
try
{
int ch;
while((ch=System.in.read())!=-1)
{ //
从键盘接收字符并向客户端发送
sout.write((byte)ch);
if(ch=='/n')
sout.flush(); //
将缓冲区内容向输出流发送
}
}
catch(Exception e)
{
System.out.println(e);
}
}
}
public void finalize() //
析构方法
{
try
{
server.close(); //
停止ServerSocket服务
}
catch(IOException e)
{
System.out.println(e);
}
}
}
由于该程序运行时,等待客户端程序的连接请求,所以必须与客户端程序同时运行,才能看见运行结果。