您的位置:首页 > 理论基础 > 计算机网络

Java开发实战1200例(第二卷)学习笔记—网络应用基础

2017-08-14 14:44 501 查看

第10章网络应用基础

10.1 网络地址解析

实例297:获取本地主机的IP地址

通过InetAddress类的getLocalHost()方法获得本地主机的InetAddress对象

调用该对象的getHostAddress()方法获得本地主机的IP地址。

主要代码如下:

//创建本地主机的InetAddress对象
InetAddress inetAddr=InetAddress.getLocalHost();
//获得本地主机的IP地址
String ip=inetAddr.getHostAddress();


以下摘录自Jdk 1.8谷歌翻译

public static InetAddress getLocalHost() throws

UnknownHostException
返回本地主机的地址。

这是通过从系统检索主机的名称,然后将该名称解析为InetAddress 。 注意:解决的地址可能会缓存一段时间。

如果有一个安全管理器,它的checkConnect方法被调用本地主机名, -1作为参数来查看是否允许该操作。

如果不允许操作,则返回表示环回地址的InetAddress。 结果 :本地主机的地址。 异常 :UnknownHostException

- 如果本地主机名无法解析成地址。
public String getHostAddress()
返回文本显示中的IP地址字符串。 结果 :原始IP地址为字符串格式。 从以下版本开始: JDK1.0.2

实例298:获取本地主机的域名和主机名

通过InetAddress类的getLocalHost()方法获得本地主机的InetAddress对象

调用getHostName()方法获得本地主机的名

调用getCanonicaHostName()方法获得本地主机的域名

主要代码如下:

//创建本地主机的InetAddress对象
InetAddress inetAddr=InetAddress.getLocalHost();
//获取本地主机的域名
String canonical=inetAddr.getCanonicalHostName();
//获取本地主机的主机名
String host=inetAddr.getHostName();


注意:当获得本地主机的域名和主机名时,如果本地主机没有域名,则显示的域名和主机名重名;如果本地主机有域名,就会显示对应的域名。

以下摘录自Jdk 1.8谷歌翻译

public String getCanonicalHostName()

获取此IP地址的完全限定域名。

最好的方法,意味着我们可能无法返回FQDN取决于底层的

系统配置。

如果有安全管理员,则该方法首先使用主机名称调用其checkConnect方法,并-1作为参数,以查看主叫代码是否被允许知道该IP地址的主机名,即连接到主机。

如果不允许操作,它将返回IP地址的文本表示。 结果 :该IP地址的完全限定域名,或者安全检查不允许操作时,该IP地址的文本表示。

从以下版本开始: 1.4

public String getHostName() 获取此IP地址的主机名。

如果此InetAddress是使用主机名创建的,则该主机名将被记住并返回;

否则,将执行反向名称查找,并将基于系统配置的名称查找服务返回结果。

如果有一个安全管理器,它的checkConnect方法首先被调用与主机名和-1作为参数,看看是否允许操作。

如果不允许操作,它将返回IP地址的文本表示。 结果 :该IP地址的主机名,或者安全检查不允许操作时,IP地址的文本表示。

实例299:通过域名获得IP地址

通过InetAddress类的getByName()方法,获得网络中指定域名的InetAddress对象

调用该对象的getHostAddress()方法,获得具有该域名的主机IP地址

主要代码如下:

//获得输入的域名
String domain=tf_domain.getText();
//创建InetAddress对象
InetAddress inetAddr=InetAddress.getByName(domain);
//获得IP地址
String ip=inetAddr.getHostAddress();


以下摘录自Jdk 1.8谷歌翻译

public static InetAddress getByName(String host) throws UnknownHostException

主机名称可以是机器名称,例如“ java.sun.com ”或其IP地址的文本表示。 如果提供了文字IP地址,则只会检查地址格式的有效性。

为host在字面的IPv6地址指定的,无论是在RFC 2732或RFC中定义的2373字面IPv6地址格式中定义的形式被接受。

还支持IPv6作用域地址。 见here对IPv6的范围地址的描述。

如果主机是null则返回一个InetAddress回送接口地址的InetAddress。

参数:host - 指定的主机,或 null 。

结果:给定主机名的IP地址。

异常:UnknownHostException -

如果没有找到 host IP地址,或者是否为全局IPv6地址指定了scope_id。

SecurityException -

如果安全管理器存在,并且其checkConnect方法不允许该操作

实例300:通过IP地址获得域名和主机名

将IP地址转换成字节数组

通过InetAddress类的getByAddress()方法,获得主机中具有指定IP地址的InetAddress对象

调用该对象的getCanonicalHostName()方法,获得对应的域名

通过getHostName()方法,获得对应的主机名。

主要代码如下:

//将IP地址转换为字节数组
String ip=tf_ip.getText();//输入IP地址字符串
String[] ipStr=ip.split("[.]");//转换成字符数组
byte[] ipBytes=new byte[4];
for(int i=0;i<4;i++){
int m=Integer.parseInt(ipStr[i])//转换成整数
byte b=(byte)(m&0xff);//转换为字节
ipBytes[i]=b;//赋值给字节数组
}
//创建本地主机的InetAddress对象 InetAddress inetAddr=InetAddress.getLocalHost(); //获取本地主机的域名 String canonical=inetAddr.getCanonicalHostName(); //获取本地主机的主机名 String host=inetAddr.getHostName();


实例301 获得内网的所有IP地址

获得本机IP地址所属的网段

ping网络中的IP地址

通过输入流对象读取所ping结果,并判断是否为内网的IP地址

主要代码如下:

//获取本机IP地址所属的网段
//获得本机的InetAddress对象
InetAddress host=InetAddress.getLocalHost();
//获得本机的IP地址
String hostAddress=host.getHostAddress();
//获得IP地址中最后一个点的位置
int pos=hostAddress.lastIndexOf(".");
//对本机的IP地址进行截取,获得网段
String wd=hostAddress.substring(0,pos+1);
//对局域网的IP地址进行遍历
for(int i=1;i<=255;i++){
String ip=wd+i;
PingIpThread thread=new PingIpThread(ip);
thread.start();
}
//获得集合中键的Set视图
Set<String> set=pingMap.keySet();
Iterator<String> it=set.itrator();//获得迭代器对象
while(it.hasNext()){
String key=it.next();
String value=pingMap.get(key);
if(value.equals("true")){
ta_allIp.append(key+"\n");
}
}


//ping网络中的IP地址,通过输入流对象读取所Ping结果,并判断是否为内网的IP地址
//获得所ping的IP进程,-w 280 是等待每次回复的超时时间,-n 1 是要发送的回显请求数
Process process=Runtime.getRuntime().exec("ping"+ip+"-w 280 -n 1");
InputStream is=process.getInputStream();//获得进程的输入流对象
InputStream is=process.getInputStreamReader(is);//创建InputStreamReader对象
BufferReader in=new BufferedReader(isr);//创建缓冲字符流对象
String line=in.readLine();//读取信息
while(line!=null){
if(line!=null&&!line.equals("")){
if(line.substring(0,2).equals("来自")
||(line.length()>10&&line.substring(0,10)
.equals("Reply from"))){//判断是ping通过的IP地址
pingMap.put(ip,"true");//向集合中添加IP地址
}
}
line=in.readLine();//再读取信息
}


10.2网络资源管理

实例302:获取网络资源的大小

-通过URLContentLength()方法获得网络资源大小

-在文本框中显示

//获得网络资源大小
public long netSourcesSize(String sUrl) throws Exception{
URL url=new URL(sUrl);//创建URL对象
URLConnection urlConn=url.openConnection();//获得网络连接对象
urlConn.connect();//dakai url引用资源的通信链接
return urlConn.getContentLength();//以字节为单位返回资源的大小
}
//在文本框中显示
String address=textFile.getText().trim();//获得输入的网址
long len=netSourceSize(address);//调用方法获取网络资源的大小
textFile_1.setText(String.valueOf(len)+"字节");//在文本框中显示网络资源的大小


实例303:解析网页中的内容

-通过URLConnection类的getInputStream()方法获得网页资源的输入流对象

-从该输入流中读取信息

//解析网页内容
public Collection<String>  getURLCollection(String urlString){
URL url=null;//声明URL
URLConnection<String> urlCollection=new ArrayList<String>();//创建集合对象
try{
url=new URl(urlString);//创建URL对象
conn=url.openConnection();//获得连接对象
conn.connect();//打开到url引用资源的通信连接
InputStream is=conn.getInputStrean();//获取流对象
InputStreamReader in=new INputStreanReader(is,"UTF-8");//转换为字符流
BufferedReader br=new BufferedReader(in);//创建缓冲流对象
String nextLine=br.readLine();//读取信息,解析网页
while(nextLine!=null){
urlCollection.add(nextLine);//解析网页的全部内容,添加到集合中
nextLine=br.readLine();//读取信息,解析网页
}
}catch(Exception ex){
ex.printStackTrance();
}
return urlCollection;
}
//输出信息
String address=tf_address.getText().trim();//获得输入的网址
Collection urlCollection=getURLCollection(address);//调用方法,获得网页内容的集合对象
Iterator it=urlCollection.iterator();//获得集合的迭代器对象
while(it.hasNext()){
ta_contet.append((String)it.next()+"\n");//在文本域中显示解析的内容
}


实例304:网络资源的单线程下载

-利用URLConnection对象的getInputStream()方法,获得网络资源的输入流对象

-使用FileOutputStream类创建输出流对象,然后使用该类的write()方法,将从输入流获得的网络资源保存到磁盘上,实现网络资源的单线程下载。

//定义download()方法,用于根据参数urlAddr指定的地址,完成网络资源的单线程下载
public void download(String urlAddr){//从指定网址下载文件
try{
URL url=new URL(urlAddr);//创建URL对象
URLConnection urlConn=url.openConnection();//获得连接对象
urlConn.connect();//打开到url引用资源的通信链接
InputStream in=urlConn.getInputStream();//获得输入流对象
int pos=filePath.lastIndexOf("/");//获得路径中最后一个斜杠的位置
String fileName=filePath.substring(pos+1);//截取文件名
FileOutputStream out=new FileOutStream("C:/"+fileName);//创建输出流对象
byte[] bytes=new byte[1024];//声明存放下载内容的字节数组
int len=in.read(bytes);//从输入流中读取内容
while(len!=-1){
out.write(bytes,0,len);//将读取的内容写到输出流
len=in.read(bytes);//继续从输入流中读取内容
}
out.close();//关闭输出流
in.close();//关闭输入流
JOptionPane.showMessageDialog(null,"下载完毕");
}catch(Exception e){
e.printStackTrance();
}
}


注意:在下载网络资源时,需要及时关闭IO流,因为每个IO流都会占用较多的系统资源,并且IO流并不能被垃圾回收机制回收,当下载网络资源的用户较多时,就会造成不必要的资源浪费,甚至会使系统崩溃。

实例305:网络资源的多线程下载

-创建线程类

-使用RandomAccessFile类的seek()方法定位下一个写入点

-通过write()方法写入文件

//实现通过线程类DownMultiThread下载网络资源
public void download(String url, String dest, int threadNum)
throws Exception {
URL downURL = new URL(url);// 创建网络资源的URL
HttpURLConnection conn = (HttpURLConnection) downURL.openConnection();// 打开网络边接
long fileLength = -1;// 用于存储文件长度的变量
int stateFlagCode = conn.getResponseCode();// 获得连接状态标记代码
if (stateFlagCode == 200) {// 网络连接正常
fileLength = conn.getContentLength();// 获得文件的长度
conn.disconnect();// 取消网络连接
}
if (fileLength > 0) {
long byteCounts = fileLength / threadNum + 1;// 计算每个线程的字节数
File file = new File(dest);// 创建目标文件的File对象
int i = 0;
while (i < threadNum) {
long startPosition = byteCounts * i;// 定义开始位置
long endPosition = byteCounts * (i + 1);// 定义结束位置
if (i == threadNum - 1) {
DownMultiThread fileThread = new DownMultiThread(url, file,
startPosition, 0);// 创建DownMultiThread线程的实例
new Thread(fileThread).start();// 启动线程对象
} else {
DownMultiThread fileThread = new DownMultiThread(url, file,
startPosition, endPosition);// 创建DownMultiThread线程的实例
new Thread(fileThread).start();// 启动线程对象
}
i++;
}
JOptionPane.showMessageDialog(null, "完成网络资源的下载。");
}
}
//创建一个实现Runnable接口的线程类DownMultiThread,用于实现网络资源的下载
public class DownMultiThread implements Runnable{
private String sUrl = "";// 网络资源地址
private File desFile;// 需要写入的目标文件对象
private long startPos;// 写入的开始位置
private long endPos;// 写入的结束位置
public DownMultiThread(String sUrl,File desFile,long startPos,long endPos) {
this.sUrl = sUrl;
this.desFile = desFile;
this.startPos = startPos;
this.endPos = endPos;
}
@Override
public void run() {
try {
URL url = new URL(sUrl);// 创建下载资源的URL对象
HttpURLConnection conn = (HttpURLConnection)url.openConnection();// 打开连接对象
conn.setRequestProperty("User-Agent", "NetFox");// 设置请求属性
String rangeProperty = "bytes="+startPos+"-";// 定义范围属性
if (endPos > 0){
rangeProperty = "bytes="+startPos+"-" + endPos;// 调整范围属性的值
}
conn.setRequestProperty("RANGE", rangeProperty);// 指定范围属性
RandomAccessFile out = new RandomAccessFile(desFile, "rw");// 创建可读写的流对象
out.seek(startPos);// 指定读写的开始标记
InputStream in = conn.getInputStream();// 获得网络资源的输入流对象
BufferedInputStream bin = new BufferedInputStream(in);// 创建输入缓冲流对象
byte[] buff = new byte[2048];// 创建字节数组
int len = -1;// 声明存放读取字节数的变量
len=bin.read(buff);// 读取到内容并添加到字节数组
while (len!=-1){
out.write(buff,0,len);// 写入磁盘文件
len=bin.read(buff);// 读取到内容并添加到字节数组
}
out.close();// 关闭流
bin.close();// 关闭流
conn.disconnect();// 断开连接
}catch(Exception ex) {
JOptionPane.showMessageDialog(null, ex.getMessage());
}
}
}


实例306下载网络资源的断点续传

本实例主要是通过设置请求参数RANGE实现的,通过该参数,可以指定下载网络资源的字节区间,从而实现每次下载部分网络资源的功能。

全部代码如下:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;

@SuppressWarnings("serial")
public class BreakPointSuperveneFrame extends JFrame {
private JTextField tf_totalLength;
private JTextField tf_residuaryLength;
private JTextField tf_readToPos;
private JTextField tf_address;
private JTextField tf_endPos;
private JTextField tf_startPos;
private String urlAddress = "";// 用于存储网络资源的地址
private long totalLength = 0;// 存储网络资源的大小,以字节为单位
private long readToPos = 0;// 存储上次读取到的位置
private long residuaryLength = 0;// 存储未读内容的大小

/**
* Launch the application
*
* @param args
*/
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
BreakPointSuperveneFrame frame = new BreakPointSuperveneFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

/**
* Create the frame
*/
public BreakPointSuperveneFrame() {
super();
getContentPane().setLayout(null);
setTitle("下载网络资源的断点续传");
setBounds(100, 100, 514, 238);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

tf_startPos = new JTextField();
tf_startPos.setBounds(80, 165, 113, 22);
getContentPane().add(tf_startPos);

final JLabel label = new JLabel();
label.setText("起始位置:");
label.setBounds(10, 167, 74, 18);
getContentPane().add(label);

final JLabel label_1 = new JLabel();
label_1.setText("结束位置:");
label_1.setBounds(199, 167, 74, 18);
getContentPane().add(label_1);

tf_endPos = new JTextField();
tf_endPos.setBounds(267, 165, 117, 22);
getContentPane().add(tf_endPos);

final JLabel label_2 = new JLabel();
label_2.setText("网络资源的地址:");
label_2.setBounds(10, 52, 113, 18);
getContentPane().add(label_2);

tf_address = new JTextField();
tf_address.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
try {
urlAddress = tf_address.getText().trim();
URL url = new URL(urlAddress);// 获得网络资源的URL
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();// 获得连接对象
connection.connect();// 连接网络资源
totalLength = connection.getContentLength();// 获得网络资源的长度
connection.disconnect();// 断开连接
tf_totalLength.setText(String.valueOf(totalLength));// 显示总长度
tf_readToPos.setText("0");// 显示上次读取到的位置
residuaryLength = totalLength;// 未读内容为文件总长度
tf_residuaryLength.setText(String.valueOf(residuaryLength));// 显示未读内容
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
}

}
});
tf_address.setBounds(119, 50, 365, 22);
getContentPane().add(tf_address);

final JLabel label_3 = new JLabel();
label_3.setForeground(new Color(0, 0, 255));
label_3.setFont(new Font("", Font.BOLD, 14));
label_3.setText("输入网络资源的地址并回车,可以获得网络资源的大小。");
label_3.setBounds(10, 10, 384, 22);
getContentPane().add(label_3);

final JLabel label_4 = new JLabel();
label_4.setForeground(new Color(128, 0, 0));
label_4.setText("网络资源的大小为");
label_4.setBounds(10, 76, 113, 38);
getContentPane().add(label_4);

final JLabel label_5 = new JLabel();
label_5.setText("上次读取到");
label_5.setBounds(10, 123, 74, 18);
getContentPane().add(label_5);

tf_readToPos = new JTextField();
tf_readToPos.setBounds(80, 121, 113, 22);
tf_readToPos.setEnabled(false);
getContentPane().add(tf_readToPos);

final JLabel label_6 = new JLabel();
label_6.setText("字节处,还剩");
label_6.setBounds(202, 123, 87, 18);
getContentPane().add(label_6);

tf_residuaryLength = new JTextField();
tf_residuaryLength.setBounds(285, 120, 117, 22);
tf_residuaryLength.setEnabled(false);
getContentPane().add(tf_residuaryLength);

final JLabel label_7 = new JLabel();
label_7.setText("字节未读。");
label_7.setBounds(404, 123, 80, 18);
getContentPane().add(label_7);

final JLabel label_4_1 = new JLabel();
label_4_1.setForeground(new Color(128, 0, 0));
label_4_1.setText("个字节。");
label_4_1.setBounds(404, 76, 80, 38);
getContentPane().add(label_4_1);

tf_totalLength = new JTextField();
tf_totalLength.setBounds(119, 84, 283, 22);
tf_totalLength.setEnabled(false);
getContentPane().add(tf_totalLength);

final JButton button = new JButton();
button.setBounds(395, 162, 89, 28);
getContentPane().add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
if (totalLength == 0) {
JOptionPane.showMessageDialog(null,
"没有网络资源。\n\n请输入正确的网址,然后回车。");
return;
}
long startPos = 0;// 起始位置
long endPos = 0;// 结束位置
try {
startPos = Long.parseLong(tf_startPos.getText().trim());// 起始位置
endPos = Long.parseLong(tf_endPos.getText().trim());// 结束位置
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "输入的起始位置或结束位置不正确。");
return;
}
readToPos = endPos;// 记录读取到的位置
residuaryLength = totalLength - readToPos;// 记录未读内容的大小
tf_readToPos.setText(String.valueOf(readToPos));// 显示读取到的位置
tf_residuaryLength.setText(String.valueOf(residuaryLength));// 显示未读字节数
tf_startPos.setText(String.valueOf(readToPos));// 设置下一个读取点的开始位置
tf_endPos.setText(String.valueOf(totalLength));// 设置下一个读取点的结束位置
tf_endPos.requestFocus();// 使结束位置文本框获得焦点
tf_endPos.selectAll();// 选择结束位置文本框中的全部内容,方便输入结束位置值
download(startPos, endPos);// 调用方法进行下载
}
});
button.setText("开始下载");
}

public void download(long startPosition, long endPosition) {
try {
URL url = new URL(urlAddress);// 获得网络资源的URL
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();// 获得连接对象
connection.setRequestProperty("User-Agent", "NetFox");// 设置请求属性
String rangeProperty = "bytes=" + startPosition + "-";// 定义请求范围属性
if (endPosition > 0) {
rangeProperty += endPosition;// 调整请求范围属性
}
connection.setRequestProperty("RANGE", rangeProperty);// 设置请求范围属性
connection.connect();// 连接网络资源
InputStream in = connection.getInputStream();// 获得输入流对象
String file = url.getFile();// 获得文件对象
String name = file.substring(file.lastIndexOf('/') + 1);// 获得文件名
FileOutputStream out = new FileOutputStream("c:/" + name, true);// 创建输出流对象,保存下载的资源
byte[] buff = new byte[2048];// 创建字节数组
int len = 0;// 定义存储读取内容长度的变量
len = in.read(buff);// 读取内容
while (len != -1) {
out.write(buff, 0, len);// 写入磁盘
len = in.read(buff);// 读取内容
}
out.close();// 关闭流
in.close();// 关闭流
connection.disconnect();// 断开连接
if (readToPos > 0 && readToPos == totalLength) {
JOptionPane.showMessageDialog(null, "完成网络资源的下载。\n单击“确定”按钮退出程序。");
System.exit(0);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}


参考书籍《Java开发实战1200例》(第二卷)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐