基础知识
1.InetAddress类
在网络API套接字,InetAddress类和它的子类型对象使用域名DNS系统,处理主机名到主机IPv4或IPv6地址的转换。如图1-1所示。
由于InetAddress类只有一个构造函数,且不能传递参数,所以不能直接创建该对象实例,比如下面的做法就是错误的:
InetAddress ia = new InetAddress (); × |
可通过以下5个成员方法获得InetAddress对象或InetAddress数组:
l getAllByName(String host)方法返回一个InetAddress对象的引用,每个对象包含一个表示相应主机名的单独的IP地址,这个IP地址是通过host参数传递的,例如:
InetAddress [] ia = getAllByName(“MyHost”); |
l getByAddress(byte [] addr)方法返回一个InetAddress对象的引用,这个对象包含了一个Ipv4地址或Ipv6地址,Ipv4地址是一个4字节数组,Ipv6地址是一个16字节地址数组。
l getByAddress(String host, byte [] addr)方法返回一个InetAddress对象的引用,这个InetAddress对象包含了一个由host和4字节的addr数组指定的IP地址,或者是host和16字节的addr数组指定的IP地址。
l getByName(String host)方法返回一个InetAddress对象,该对象包含了一个与host参数指定的主机相对应的IP地址。
l getLocalHost()方法返回一个InetAddress对象,这个对象包含了本地机的IP地址。
以上各方法均可能产生的UnknownHostException(未知的主机名)异常。当获得了InetAddress类对象的引用就可以调用InetAddress的各种方法来获得InetAddress子类对象中的IP地址信息。例,通过调用getCanonicalHostName()从域名服务中获得标准的主机名,getHostAddress()获得IP地址,getHostName()获得主机名,isLoopbackAddress()判断IP地址是否是一个loopback环回地址。
2.URL类
IP地址唯一标识了Internet上的计算机,而URL则标识了这些计算机上的资源。通常,URL是一个包含了传输协议、主机名称、服务端口号、文件路径名称,以及间隔符号“://”、“:”、“/” 等信息的字符串,例:https://www.cnblogs.com/ftl1012/p/9346858.html
为了方便程序员编程,JDK中提供了URL类,该类的全名是java.net.URL,该类用于使用它的各种方法来对URL对象进行分割、合并等处理,如图1-2所示。
URL有6种构造方法,通常使用了绝对URL路径构造方法,其中的URL参数是一个完整的URL字符串,而且必须要包含传输协议,如:
URL raceHtml=new URL("https://www.cnblogs.com/ftl1012/p/9346858.html"); |
四、常用方法
1. InetAddress类主要方法
byte[] |
getAddress() 返回该对象的原始IP。 |
static InetAddress[] |
getAllByName(String host) 获得指定主机域名的所有IP地址。 |
static InetAddress |
getByAddress(byte[] addr) 获得指定IP地址对象。 |
static InetAddress |
getByAddress(String host, byte[] addr) 根据指定主机名和IP地址创建对象。 |
static InetAddress |
getByName(String host) 根据指定主机名获得对象。 |
String |
getCanonicalHostName() 获得指定域名的法定信息。 |
String |
getHostAddress() 返回当前IP地址字符串。 |
String |
getHostName() 获得当前IP地址的主机名。 |
static InetAddress |
getLocalHost() 获得本地主机。 |
boolean |
isLoopbackAddress() 判断IP是否为环回地址。 |
2. URL类主要方法
getAuthority() 获得URL的认证部分。 |
|
getContent() 获得URL的内容。 |
|
getContent(Class[] classes) 获得URL的内容 |
|
int |
getDefaultPort()获得URL默认的端口号 |
getFile() 获得URL的文件名 |
|
getHost()获得该URL的主机名 |
|
getPath() 获得该URL的路径 |
|
int |
getPort() 获得该URL的端口 |
getProtocol()获得该URL的协议。 |
|
getQuery()获得该URL的查询部分 |
|
getRef()获得该URL的锚部分 |
|
getUserInfo()获得该URL的用户信息 |
|
openConnection() 返回URL的连接。 |
|
openStream()打开URL的输入读取流 |
代码示例
根据主机名查找IP
import java.net.InetAddress;
import java.util.*; public class My
{
public static void main(String[] args)
{
String local = null ;
for(int i =18;i<20;i++){
local = "FF109Lx-"+i ;
try{
InetAddress inet = InetAddress.getByName(local) ;
byte[] ip = inet.getAddress();
System.out.print("FF109Lx-"+i);
for(int x=0;x<ip.length;x++){
int ips = (ip[x]>=0?ip[x]:(ip[x]+256)) ;
System.out.print(" "+ips+"." ) ;
}
}catch(Exception e ){
System.err.println("FF109Lx-"+i+" 获得本地信息失败..." );
System.out.println();
}
}
}
}
根据IP查找主机
package com.hhh.ftl;
import java.net.InetAddress;
import java.util.*; public class Test
{
public static void main(String[] args)
{
String local = null ;
for(int i =100;i<102;i++){
local = "192.168.1."+i ;
try{
InetAddress inet = InetAddress.getByName(local) ;
byte[] ip = inet.getAddress();
System.out.print("FF109Lx-"+i);
for(int x=0;x<ip.length;x++){
int ips = (ip[x]>=0?ip[x]:(ip[x]+256)) ;
System.out.print(" "+ips+"." ) ;
}
System.out.println("");
}catch(Exception e ){
System.err.println("FF109Lx-"+i+" 获得本地信息失败..." );
}
}
}
}
采用多线程方式探测某主机上所有的TCP端口开放情况
package com.hhh.ftl; import java.net.*;
import java.io.*;
import java.net.*; class Sum { // 共享资源,计数器count
private int count;// 共享资源 public int add() {
synchronized (this) { // 代码段1,共享锁,修饰程序段或者方法
count = count + 1;
System.out.println("add:" + count);
return count;
}
}
} class ScanThread implements Runnable {// 定义线程
private Sum sd;
private int sum = 0;
private String host; public ScanThread(String name, Sum sd, String host) {
this.sd = sd;
this.host = host;
} public void run() {// 必需的重写
int port;
try {
for (int i = 0; i < 65535; i++) {
port = sd.add();
if (port > 65535)
break;
try {
Socket cs = new Socket(host, port);
System.out.println("port" + port + "出于开放状态");
cs.close();
} catch (Exception e) {
System.err.println("port" + port + "不能连接");
}
Thread.sleep(100);
}
Thread.sleep(1000);
} catch (Exception e) {
System.err.println("sleep异常");
}
}
} public class ScanD1emo {
public static void main(String[] args) {
Sum sd = new Sum();// 代表共享资源的变量
ScanThread s1 = new ScanThread("线程1", sd, "localhost");// 创建完毕
ScanThread s2 = new ScanThread("线程2", sd, "localhost");
ScanThread s3 = new ScanThread("线程3", sd, "localhost");
Thread st1 = new Thread(s1);
Thread st2 = new Thread(s2);
Thread st3 = new Thread(s3);
try {
long begin = System.currentTimeMillis();
st1.start();// 使线程运行
st2.start();
st3.start(); st1.join();
st2.join();
st3.join();
long end = System.currentTimeMillis();
System.out.println("探测localhost的TCP端口,共耗时" + (end - begin) + "毫秒");
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
使用InetAddress类,用于获得指定的计算机名称和IP地址
采用了URL类,用于解析在单行编辑框中输入的URL地址,分解出访问协议、主机名称、端口号以及文件路径名称等。
package com.hhh.ftl;
import java.net.URL;
import java.net.MalformedURLException;
public class myURL{
URL url;
public myURL(String urlStr){
try{
url = new URL(urlStr);
}catch(Exception e){
System.err.println(e.getMessage());
}
}
public void resolve(){
System.out.println(url.getProtocol());
System.out.println(url.getHost());
System.out.println(url.getPort());
System.out.println(url.getPath());
System.out.println(url.getFile());
System.out.println(url.getQuery());
System.out.println(url.getRef());
}
public static void main(String [] args){
myURL my = new myURL("https://www.cnblogs.com/ftl1012/p/9346858.html");
my.resolve();
}
}
图形化的URL输入和分析
package com.hhh.ftl;
import java.net.URL;
import java.net.MalformedURLException;
import java.awt.*;
import java.awt.event.*;
public class getURLInformation extends Frame{
TextField tUrl = new TextField("输入URL地址");
List lItems = new List(20);
Button bOk = new Button("解 析");
Font f = new Font("Serif",Font.BOLD,30);
public getURLInformation(){
this.setLayout(new BorderLayout());
this.add(tUrl, BorderLayout.NORTH);
this.add(lItems, BorderLayout.CENTER);
this.add(bOk, BorderLayout.SOUTH);
tUrl.setFont(f);
lItems.setFont(f);
bOk.setFont(f);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
System.exit(0);
}
});
bOk.addActionListener(new Listener());
}
public static void main(String args[]){
System.out.println("Starting New...");
getURLInformation mainFrame = new getURLInformation();
mainFrame.setSize(400, 400);
mainFrame.setTitle("解析URL");
mainFrame.setVisible(true);
}
class Listener implements ActionListener{
public void actionPerformed(ActionEvent e){
URL getURL = null; try{
getURL = new URL(tUrl.getText());
}catch(MalformedURLException e1){
System.out.println("URL解析错误" + e1);
}
lItems.add("Reference:" + getURL.getRef(), 0);
lItems.add("File Name:" + getURL.getFile(), 0);
lItems.add("File Path:" + getURL.getPath(), 0);
lItems.add("Host Port:" + getURL.getPort(), 0);
lItems.add("Host Name:" + getURL.getHost(), 0);
lItems.add("Protocol :" + getURL.getProtocol(), 0);
} } }
通过URL获得网页上文本资源
package com.hhh.ftl;
import java.io.*;
import java.net.*;
public class Test{
public static void main(String [] args) throws Exception{
String url = "https://www.cnblogs.com/ftl1012/p/9346858.html"; //自行输入URL,例如https://www.cnblogs.com/ftl1012/p/9346858.html;
InputStream in = (new URL(url)).openStream(); //获得指定URL的字节输入流
int c = -1;
while((c = in.read()) != -1){ //按字节的方式输入数据和输出数据
System.out.write(c);
} } }
通过URL获得网页上图像资源
import java.io.*;
import java.net.*;
class exp_4_8{
public static void main(String [] args){
try{
InputStream imageSource = new URL(网络图片的URL).openStream();
FileOutputStream myFile = new FileOutputStream("c://myLogo.gif");
BufferedOutputStream myBuffer = new BufferedOutputStream(myFile);
DataOutputStream myData = new DataOutputStream(myBuffer);
int ch;
while((ch = imageSource.read()) > -1){ //由网络输入数据
myData.write(ch); //将数据输出到文件中
}
myBuffer.flush(); //将文件缓存中数据写入文件
imageSource.close();
myFile.close();
myBuffer.close();
myData.close();
}catch(Exception e){
System.err.print(e.toString());
} } }
获得JVM系统信息,记录在当前运行该程序的JVM信息
利用URL类型实现从指定地址获得文本格式的HTML源文件
实现利用InetAddress.getByName()按计算机名称获得实验室局域网中所有开机主机名称和IP地址
实现利用InetAddress.getByName()按IP地址获得指定网络段所有开机主机名称/域名和IP地址
package com.mc.test1; import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.*;
public class Main { public static void main(String[] args) throws Exception { System.out.println("\n"+"------------------------------------------");
System.out.println("PIng时间为2秒") ;
for(int i=18;i<30;i++){
String local = "FF109Lx-"+i ;
try{
InetAddress inet = InetAddress.getByName(local);
System.out.println(inet);
System.out.println("局域网内的主机名称:"+inet.getHostName()); //获得主机名称
byte [] ip = inet.getAddress(); //获得主机IP地址
for(int x=0;x<ip.length;x++){
int ips = (ip[x] >=0) ? ip[x] : (ip[i] + 256); //将byte数值转换为int数值
System.out.print(ips + ".");
}
inet.isReachable(2000) ;
}catch(Exception e){
System.err.println("获得信息失败" + e.toString());
}
} }
}
实现1-30的累计,其*享资源池为1-30的数字的递增,采用了同步锁synchronized【待修改】
class Sum{ //共享资源,计数器count
private int count;//共享资源
public int add(){
synchronized(this){ //代码段1,共享锁,修饰程序段或者方法
count = count + 1;
System.out.println("add:" + count);
return count;
}
}
}
class SumThread implements Runnable{//定义线程
private Sum sd;
private int sum = 0;
private int [] a = new int[10]; public SumThread(String name, Sum sd){
super(name);
this.sd = sd;
}
public void run(){//必需的重写
try{
for(int i=0;i<10;i++){
a[i] = sd.add();
sum += a[i];
Thread.sleep(100);
}
Thread.sleep(1000);
}catch(Exception e){} System.out.println(getName() + "累加和:" + sum);
}
public void showData(){
System.out.print(getName() + "获得的数为");
for(int i=0;i<10;i++){
if(i%10==0)System.out.println();
System.out.print(a[i] + "+\t");
}
}
public int getSum(){
return sum;
}
}
public class SumDemo{
public static void main(String [] args){
Sum sd = new Sum();//代表共享资源的变量
SumThread s1 = new SumThread("线程1",sd);//创建完毕
SumThread s2 = new SumThread("线程2",sd);
SumThread s3 = new SumThread("线程3",sd);
Thread st1 = new Thread(s1);
Thread st2 = new Thread(s2);
Thread st3 = new Thread(s3);
st1.setPriority(Thread.MAX_PRIORITY); //代码段2
st2.setPriority(10);
st3.setPriority(1);
long begin = System.currentTimeMillis();
st1.start();//使线程运行
st2.start(); st3.start();
St1.join(); st2.join(); st3.join();
st1.showData();
st2.showData();
st3.showData();
System.out.println("总和为:" + (st1.getSum() + st2.getSum() + st3.getSum()));
long end = System.currentTimeMillis();
System.out.println(“探测localhost的TCP端口,共耗时” +
( end - begin)+"毫秒");
} }