InetAddress 类是java包装用来表示IPd地址的高级表示,InetAddress 不能通过new 方法来获得对象,需要使用类的静态方法来获得一个InetAddress对象
下面就InetAddress所提供的一些类做一个简单的介绍。
1.InetAddress.getByName()
通过主机名获取对应的ip地址:(当然也支持通过IP地址来查找主机名)
该方法会建立与本地DNS的一个连接,来获取名称和地址之间的映射关系。(如果本地DNS缓存了地址,就不再获取连接。)
2**.InetAddress.getLocalHost()**
得到真正的主机名和IP地址。如果获取失败,则会返回一个会送地址,即主机名为“localhost”,以及一个点四分段的ip:‘127.0.0.1’ 。
3**缓存**
由于DNS查找的开销很大,并且如果一个地址不可达,可能会需要几秒钟的时间来确认。InetAddress提供了缓存机制,一旦得到一个给定主机的地址,就会缓存起来,即使重新定义一个InetAddress类,也不会重新再获取一次,而是直接从缓存中获取。但是需要注意一种情况。就是DNS在传输过程中可能的超时。当第一次请求是发生超时失败,而第二次的时候请求已经到达,并缓存了起来。所有Java在缓存不可达的地址时,只缓存了10s。
4.安全性问题
从主机名创建一个InetAddress对象,被认为是一种不安全的操作。因为这需要一个DNS查找,在默认的安全管理控制器下的不可行applet只允许获取它本机的主机地址以及ip。不允许不可行代码由任何其他主机名创建InetAddress对象。不可信的代码不允许对第三方主机完成任意查找。
5.获取方法
public String getHostName()
publlic String getCanonicalHostName()
public byte[] getAddress()
public String getHostAddress()
没有对应的setHostName()以及getHostName()。代表着无法通过反射来改变其内部的。因此是线程安全的。
6.地址类型
ip地址分为不同的类型,例如:‘’127.0.0.1‘’属于本地回送地址。Java提供了10中方法来判断一个ip地址属于那种不同的分段。
public boolean isAnyLocalAddress()
URL 统一资源定位符,
创建方法:
//创建URL实例
URL imooc = new URL("http://www.baidu.com");
可以将URL包装成一个新的URL对象
//?后面表示参数#后面表示锚点
URL url = new URL(imooc, "/index.html?username=tom#test");
创建URL并访问资源的代码如下:
package xxlong.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.io.InputStream;
import java.io.InputStreamReader;
public class URLTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
//创建URL实例
URL imooc = new URL("http://www.baidu.com");
InputStream is = imooc.openStream();
InputStreamReader isr = new InputStreamReader(is, "utf-8");
BufferedReader br = new BufferedReader(isr);
String data = br.readLine();
while(data!=null) {
System.out.println(data);
data = br.readLine();
}
br.close();
isr.close();
is.close();
/*
//?后面表示参数#后面表示锚点
URL url = new URL(imooc, "/index.html?username=tom#test");
System.out.println("协议:" + url.getProtocol());
System.out.println("文件路径: " + url.getPath());
//如果没有设置端口号,则使用默认端口号,方法返回-1
System.out.println("端口: " + url.getPort());
System.out.println("主机: " + url.getHost());
System.out.println("文件名:" + url.getFile());
System.out.println("相对路径:" + url.getRef());
System.out.println("查询字符串:" + url.getQuery());
System.out.println("" + url.getAuthority());
System.out.println(" " + url.getContent());
*/
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Socket
网络上的两个程序通过一个双向的通信连接实现的数据交换,这个连接的一段称为一个socket,
TCP协议:transmission control protocol,传输控制协议,是一种面向连接的、可靠地、基于字节流的传输层通信协议
使用socket进行tcp通信时,首先需要创建一个服务器端,然后创建一个客户端,然后进行连接,创建ServerSocket的步骤:
1,创建ServerSocket对象,一般需要指定端口号
ServerSocket serverSocket = new ServerSocket(8889);
2,调用accept方法开启监听
socket = serverSocket.accept();
3,通过socket的getgetInputStream()方法获取输入流,读取客户端信息
is = socket.getInputStream();
//包装成字符流,以提高读取的效率
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
//4.读取信息
info = br.readLine();
while(info != null) {
System.out.println(info);
info = br.readLine();
}
4,关闭socket 及相关资源
socket.shutdownInput();
5,响应客户端
os = socket.getOutputStream();
pw = new PrintWriter(os);
pw.write("欢迎咯!");
pw.flush();
socket.shutdownOutput();
6,关闭其他资源,必须关闭,因此放到finally语句中
finally {
//6.关闭其他资源
try {
if(pw != null)
pw.close();
if(os != null)
os.close();
if(br != null)
br.close();
if(isr != null)
isr.close();
if(is != null)
is.close();
if(socket != null)
socket.close();
}
ServerSocket完整代码如下
package xxlong.tet;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
public class Server {
public static void main(String[] args) {
try {
//1.创建ServerSocket
ServerSocket serverSocket = new ServerSocket(8889);
System.out.println("服务器已开启监听");
Socket socket = null;
int count = 0;
//2.开启监听
while(true) {
socket = serverSocket.accept();
ServerThread st = new ServerThread(socket);
st.start();
count++;
System.out.println("当前客户端数量:" + count);
InetAddress ia = socket.getInetAddress();
System.out.println("IP: " + ia.getHostAddress());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
服务器线程:
package xxlong.tet;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
public class ServerThread extends Thread {
Socket socket = null;
public ServerThread(Socket socket) {
this.socket = socket;
}
//多线程处理Socket通信
public void run() {
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
String info = null;
OutputStream os = null;
PrintWriter pw = null;
try {
is = socket.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
//4.读取信息
info = br.readLine();
while(info != null) {
System.out.println(info);
info = br.readLine();
}
//5.关闭Socket输入流
socket.shutdownInput();
os = socket.getOutputStream();
pw = new PrintWriter(os);
pw.write("欢迎咯!");
pw.flush();
socket.shutdownOutput();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
//6.关闭其他资源
try {
if(pw != null)
pw.close();
if(os != null)
os.close();
if(br != null)
br.close();
if(isr != null)
isr.close();
if(is != null)
is.close();
if(socket != null)
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
客户端
1,客户端创建socket
Socket socket = new Socket("localhost", 8889);
指定地址及端口号
2,获得字节输出流,向服务器发送信息
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.write("用户名:user2;密码:123456");
pw.flush();
socket.shutdownOutput();
3,读取服务器端响应
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String info = br.readLine();
while(info != null) {
System.out.println(info);
info = br.readLine();
}
4,关闭资源
br.close();
isr.close();
is.close();
pw.close();
os.close();
socket.close();
UDP通信
UDP:user datagram protocol 用户数据报协议,是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
UDP通信服务器端
package xxlong.test;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.net.InetAddress;
public class Server {
public static void main(String[] args) {
try {
//创建DatagramSocket
DatagramSocket socket = new DatagramSocket(8888);
//缓存数据数组
byte[] data = new byte[1024];
//创建DatagramPacket
DatagramPacket packet = new DatagramPacket(data, data.length);
System.out.println("服务器已经启动");
//接受客户端信息
socket.receive(packet);//此方法接收到数据报之前会一直阻塞
String info = new String(packet.getData(), 0, packet.getLength());
System.out.println("服务端接收到信息:" + info);
InetAddress address = packet.getAddress();
int port = packet.getPort();
//响应客户端
byte[] datato = "欢迎使用".getBytes();
DatagramPacket packet2 = new DatagramPacket(datato, datato.length, address, port);
socket.send(packet2);
System.out.println("已响应");
//关闭socket
socket.close();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户端
package xxlong.test;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.net.DatagramSocket;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
//获取IP
InetAddress address = InetAddress.getByName("localhost");
//指定端口号
int port = 8888;
//要发送信息
byte[] data = "用户名:user;密码:123456".getBytes();
//创建数据报并指定发送地址及端口号
DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
//创建DatagramSocket
DatagramSocket socket = new DatagramSocket();
//发送数据报
socket.send(packet);
//准备接收数据报
byte[] data2 = new byte[1024];
DatagramPacket packet2 = new DatagramPacket(data2, data2.length);
//等待系统响应
socket.receive(packet2);
System.out.println("已接收响应");
String reply = new String(data2, 0, packet2.getLength());
System.out.println("服务器说: " + reply);
//关闭socket
socket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}