day22
一、网络编程:
1、网络编程的三要素是什么?
1)找到IP地址
2)必须有端口
3)必须有协议(TCP协议,UDP协议)
2、IP地址:
PC机器都有唯一的标识:ip
ip地址:192.168.1.100 已经优化的ip
ip每一个段落转成二进制:
11000000 10101000 00000001 01100100
192 168 1 100
常见的IP:
A类:1.0.0.1—127.255.255.254:第一个号段为网络号段,后三个号段为主机号段
256^3=16777216台计算机 (强大的部门),通常:国防部(美国的五角大楼)
B类:128.0.0.1—191.255.255.254:前两个号段为网络号段,后两个号段为主机号段()
256^2: 通常大学里面或者一些地方政府部门
C类:192.0.0.1—223.255.255.254:前三个好号段为网络号段,后一个号段为主机号段
192.168.1.100(私人地址:家庭或者单位)
D类 224.0.0.1—239.255.255.254
E类 240.0.0.1—247.255.255.254
回环地址(也可表示本机地址):127.0.0.1
3、协议:
TCP协议和UDP协议 区别:
TCP协议:(客户端和服务器端的交互)
1)建立连接通道(通道内的流:(使用的是最基本的字节流))
2)可靠协议
3)由于可靠协议,并且需要建立连接通道(服务器端需要等待客户端连接),执行效率低
4)使用TCP协议(TCP编程)可以发送大量的数据,文件大小无限制
UDP协议:(发送端和接收端)
1)无需建立连接通道(数据报包的形式发送数据的)
2)不可靠协议
3)由于不可靠,无需建立连接通道,所以它的执行效率高
4)UDP协议(UDP编程)发送数据有限制
4、获取IP地址
package org.westos_01_IP地址;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* InetAddress类没有构造方法 此类表示互联网协议 (IP) 地址。
* public static InetAddress getByName(String host)throws UnknownHostException
* 在给定主机名的情况下确定主机的 IP 地址
* //public String getHostName()获取此 IP 地址的主机名。
* //public String getHostAddress()返回 IP 地址字符串(以文本表现形式)。
* @author 小鑫
*/
public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
// public static InetAddress getByName(String host)throws
// UnknownHostException在给定主机名的情况下确定主机的 IP 地址
// 该主机名可以是计算机名(PC机器的计算机名称),也可以是ip地址的文本表现形式,通过这个方法返回的是ip地址对象
//InetAddress ip = InetAddress.getByName("172.20.10.6");
//System.out.println(ip);// /172.20.10.6
InetAddress address = InetAddress.getByName("LAPTOP-IKV5PTCD");
System.out.println(address);//LAPTOP-IKV5PTCD/172.20.10.6
//public String getHostName()获取此 IP 地址的主机名。
String name = address.getHostName();
System.out.println(name);//LAPTOP-IKV5PTCD
//获取具体的IP地址文本形式
//public String getHostAddress()返回 IP 地址字符串(以文本表现形式)。
String ip = address.getHostAddress();
System.out.println(ip);//172.20.10.6
}
}
二、UDP协议
1、发送端和接收端开发步骤
package org.westos_02_UDP协议;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
/**
* UDP协议(发送端和接收端),不需要建立连接通道
* 发送端 步骤:
* 1)创建UDP协议发送端的Socket对象
* 2)创建数据报包:通过这个数据包将数据发送到接收端
* 3)调用UDP协议发送端发送的方法
* 4)关闭资源
*
* @author 小鑫
*
*/
public class SendDemo {
public static void main(String[] args) throws IOException {
//1) 创建Socket对象:DatagramSocket(客户端的套接字)
// DatagramSocket:用来发送和接收数据报包的套接字。
// public DatagramSocket() throws SocketException
DatagramSocket ds = new DatagramSocket();// 创建了UDP协议的Socket对象
// 发送一句话
String str = "hello,word";
// 2)创建数据报包对象
// public DatagramPacket(byte[] buf, int length ,InetAddress address,int
// port)
// 将字符串数据转换成字节数组
byte[] bys = str.getBytes();
// 当前字节数组的实际长度
int len = bys.length;
// 创建InetAddress对象,Ip地址对象
InetAddress address = InetAddress.getByName("172.20.10.6");
// 指定端口号:0-65535是有效端口号
int port = 12345;
DatagramPacket dp = new DatagramPacket(bys, len, address, port);
// 3)调用UDP协议DataScoket类里面发送的方法
// public void send(DatagramPacket p) throws IOException从此套接字发送数据报包
ds.send(dp);
// 4)关闭资源
ds.close();
}
}
package org.westos_02_UDP协议;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
* UDP协议接收端:
* 1)创建接收端Socket对象
* 2)创建一个数据报包接收发送端发来的数据报包
* 3)接收数据,调用DataSocket类中的接收方法接收数据
* 4)解析数据报包里面的数据,显示
* 5)关闭资源
*
*多次运行接收端,会出现一处:BindException:绑定异常:
* 接收端运行一次就可以了,端口号已经被占用了,不能再继续使用这个端口
* @author 小鑫
*
*/
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//1)创建UDP协议Socket对象
DatagramSocket ds = new DatagramSocket(12345);
//2)创建数据报包:DatagramPacket,接收数据
//public DatagramPacket(byte[] buf,int length)构造 DatagramPacket,用来接收长度为 length 的数据包。
byte[] bys=new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
//3)接收数据:public void receive(DatagramPacket p) throws IOException从此套接字接收数据报包
ds.receive(dp);// 阻塞式方法(等待发送端发送数据,只要没有数据,就一直等待,有数据的话将数据显示控制)
//4)解析
//获取到ip字符串表现形式
//public InetAddress getAddress():首先通过数据报包得到一个Ip地址对象:InetAddress
InetAddress address = dp.getAddress();
//可以通过getHostAddress()得到ip地址的文本形式
String ip = address.getHostAddress();
//byte[] getData() 返回数据缓冲区。
//int getLength() 返回将要发送或接收到的数据的长度。
byte[] dataBys = dp.getData();
int len = dp.getLength();
//将字符串显示出来
String str = new String(bys, 0, len);
System.out.println(ip+"给你发送了"+str);
//172.20.10.6给你发送了hello,word
//5)关闭
ds.close();
}
}
2、改进版
package org.westos_03_改进UDP协议;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* UDP:发送端
* @author 小鑫
*
*/
public class SendDemo {
public static void main(String[] args) throws IOException {
// 1)创建Socket对象
DatagramSocket ds = new DatagramSocket();
// 2)创建数据报包
byte[] bys = "hello,world".getBytes();
DatagramPacket dp = new DatagramPacket(bys, bys.length,
InetAddress.getByName("172.20.10.6"), 8888);
//3)将数据以数据报包发送出去
ds.send(dp);
//4)关闭资源
ds.close();
}
}
package org.westos_03_改进UDP协议;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* UDp:接收端
* @author 小鑫
*
*/
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//1)创建Socket对象
DatagramSocket ds = new DatagramSocket(8888);
//2)创建接收容器:报包
byte[] bys=new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
//3)接收数据
ds.receive(dp);
//4)解析
//获取IP地址字符串
String ip = dp.getAddress().getHostAddress();
//获取缓存区数据
byte[] bys2 = dp.getData();
//获取长度
int len = dp.getLength();
String s = new String(bys2, 0, len);
System.out.println(ip+"发来了"+s);
//5)关闭
ds.close();
}
}
3、发送端一直发送
package org.westos_04_键盘录入UDP协议;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* 发送端的数据来源不是简单的一条语句而是不停的键盘录入
*
* @author 小鑫
*
*/
public class SendDemo {
public static void main(String[] args) throws IOException {
// 创建发送端Socket对象
DatagramSocket ds = new DatagramSocket();
// 以IO流的读取键盘录入的数据发送到接收端
// 字符缓冲流
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line = br.readLine()) != null) {
// 自定义结束条件
if ("over".equals(line)) {
break;
}
// 创建数据报包
byte[] bys = line.getBytes();
DatagramPacket dp = new DatagramPacket(bys, bys.length,
InetAddress.getByName("172.20.10.6"), 6666);
//发送
ds.send(dp);
}
//释放资源
ds.close();
}
}
package org.westos_04_键盘录入UDP协议;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* 接收端不停的接收键盘录入的数据显示到控制台上
* @author 小鑫
*
*/
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//创建接收端Socket对象
DatagramSocket ds = new DatagramSocket(6666);
while(true){
byte[] bys=new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
//接收数据
ds.receive(dp);
//获取ip
String ip = dp.getAddress().getHostAddress();
//解析
byte[] buff = dp.getData();
int len = dp.getLength();
String s = new String(buff, 0, len);
System.out.println(ip+"发来了"+s);
//模仿发送端一直发送数据,不用关闭资源
}
}
}
4、多线程UDP通信
package org.westos_05_多线程_键盘录入UDP协议;
import java.net.DatagramSocket;
import java.net.SocketException;
/**
* 需求:接收端和发送端是在两个窗口中显示的,如何让这两个接收端和发送端处于一个窗口下(main中) (使用多线程第二种方式:Runable接口的方式实现
* 发送端和接收端处于一个主线程中)
*
* @author 小鑫
*
*/
public class ChatRoom {
public static void main(String[] args) {
try {
// 创建发送端和接收端Socket对象
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receiveSocket = new DatagramSocket(8866);
// 创建资源对象
SendThread st = new SendThread(sendSocket);
ReceiveThread rt = new ReceiveThread(receiveSocket);
//创建线程类对象
Thread t1 = new Thread(st);
Thread t2 = new Thread(rt);
//启动线程
t1.start();
t2.start();
} catch (SocketException e) {
e.printStackTrace();
}
}
}
package org.westos_05_多线程_键盘录入UDP协议;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class SendThread implements Runnable {
// 定义一个变量
private DatagramSocket ds;
public SendThread(DatagramSocket ds) {
this.ds = ds;
}
@Override
public void run() {
try {
// 创建发送端Socket对象
// IO流读取键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while ((line = br.readLine()) != null) {
//结束条件
if("over".equals(line)){
break;
}
// 创建数据报包
byte[] bys = line.getBytes();
DatagramPacket dp = new DatagramPacket(bys, bys.length,
InetAddress.getByName("192.168.100.15"), 8866);
//发送
ds.send(dp);
}
} catch (IOException e) {
e.printStackTrace();
}finally{
//释放资源
if(ds!=null){
ds.close();
}
}
}
}
package org.westos_05_多线程_键盘录入UDP协议;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class ReceiveThread implements Runnable{
private DatagramSocket ds;
public ReceiveThread(DatagramSocket ds){
this.ds=ds;
}
@Override
public void run() {
try {
while(true){
//创建接收端报包
byte[] bys=new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
//接收数据
ds.receive(dp);
//获取IP文本表现形式
String ip = dp.getAddress().getHostAddress();
//解析
byte[] buff = dp.getData();
int len = dp.getLength();
String s = new String(buff, 0, len);
System.out.println(ip+"发来了"+s);
}
} catch (IOException e) {
e.printStackTrace();
}
//接收要不停接收数据,不需要关闭
}
}
三、TCP协议
1、TCP协议客户端和发送端开发
package org.westos_06_TCP协议;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/**
* 使用Socket编程里面的TCP协议:
* 客户端和服务器端的交互 客户端步骤:
* 1)创建客户端的socket对象 (客户端套接字流的形式)
* 2)获取通道的内流(输出流)
* 3)使用输出流对象写数据
* 4)关闭客户端的Socket对象
*
* 对于TCP协议来说:客户端和服务器端是需要建立连接通道的,如果没有启动服务器端,先启动客户端: 报异常:java.net.ConnectException
* Connection refused: connect :连接被拒绝!
*
* @author 小鑫
*
*/
public class CilentDemo {
public static void main(String[] args) throws IOException {
// 1)创建客户端Socket对象:此类实现客户端套接字
// public Socket(InetAddress address, int port)throws
// IOException创建一个流套接字并将其连接到指定 IP 地址的指定端
// Socket s = new Socket(InetAddress.getByName("192.168.100.15"), 12345);
// public Socket(String host, int port)
// host:可以是主机名称也可是ip地址的字符串表现形式
Socket s = new Socket("192.168.100.15", 12345);
// 2)获取通道内的输出流
// public OutputStream getOutputStream()throws IOException返回此套接字的输出流。
OutputStream out = s.getOutputStream();
//3)客户端通道流给服务器写数据
out.write("hello,world".getBytes());
//4)关闭客户端Socket
s.close();
}
}
package org.westos_06_TCP协议;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* TCP协议服务器端
* 1)创建服务器端的socket对象,指定端口
* 2)服务器端需要监听客户端的连接
* 3)获取通道内的输入流
* 4)将数据获取到并显示到控制台
* 5)关闭服务器端的socket资源
* @author 小鑫
*
*/
public class ServerDemo {
public static void main(String[] args) throws IOException {
//1)public ServerSocket(int port) 构造方法:创建绑定到特定端口的服务器套接字
ServerSocket ss = new ServerSocket(12345);
System.out.println("等待客户端连接...");
//2)监听客户端
//public Socket accept() throws IOException侦听并接受到此套接字的连接
Socket s = ss.accept();
System.out.println("客户端连接成功");
//3)获取通道内的输入流对象
//public InputStream getInputStream()
InputStream in = s.getInputStream();
//4)将客户端发送数据显示控制台
byte[] bys=new byte[1024];
//获取到实际的字节数 (阻塞式方法)
int len = in.read(bys);
String str = new String(bys, 0, len);
//获取IP地址文本表现形式
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"发送来"+str);
//5)关闭服务器端
s.close();
}
}
2、服务器端反馈
package org.westos_07_TCP协议_反馈数据;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 客户端发送数据,服务器端给客户端反馈数据...
* @author 小鑫
*
*/
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建客户端Socket对象
Socket s = new Socket("192.168.100.15", 9999);
//获取通道内的输出流
OutputStream out = s.getOutputStream();
//发送服务端,写入通道
out.write("你很好".getBytes());
//获取反馈过来的数据,获取通道输入流对象
InputStream in = s.getInputStream();
//读数据
byte[] bys=new byte[1024];
int len = in.read(bys);
String client = new String(bys, 0, len);
System.out.println(client);
//关闭资源
s.close();
}
}
package org.westos_07_TCP协议_反馈数据;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
//1)获取Socket对象
ServerSocket ss = new ServerSocket(9999);
System.out.println("正在等待客户端连接");
//2)监听客户端
Socket s = ss.accept();
//阻塞式方法结束,连接了(侦听到客户端的和的服务器端端口一致)
System.out.println("客户端已连接");
//3)获取通道内输入流
InputStream in = s.getInputStream();
byte[] bys=new byte[1024];
int len = in.read(bys);
String server = new String(bys, 0, len);
System.out.println(server);
//反馈,获取通道输出流
OutputStream out = s.getOutputStream();
out.write("收到数据".getBytes());
//关闭资源
s.close();
}
}
3、客户端键盘录入
package org.westos_08_TCP协议键盘录入_反馈数据;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/**
* 客户端键盘录入数据
*
* @author 小鑫
*
*/
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 1)创建服务器端Socket对象
Socket s = new Socket("192.168.100.15", 2468);
// 2)键盘录入
// BufferedReader字符流封装数据,读取键盘录入的数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 3)获取通道输出流,使用字符缓冲输出流封装通道内的流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
//BufferedReader一次读取一行数据:readLine
String line=null;
while((line=br.readLine())!=null){
//定义结束条件
if("over".equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
//关闭资源
s.close();
}
}
package org.westos_08_TCP协议键盘录入_反馈数据;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建Socket对象
ServerSocket ss = new ServerSocket(2468);
System.out.println("等待客户端连接");
// 监听客户端
Socket s = ss.accept();
System.out.println("客户端连接成功");
// 封装服务器通道输入流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String line=null;
while((line=br.readLine())!=null){
System.out.println(line);
}
//关闭资源
s.close();
}
}
4、客户端键盘录入,服务器输出将录入的内容输出到文本文件
package org.westos_09_TCP协议键盘录入输出文本文件;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 客户端键盘录入,服务器输出将录入的内容输出到文本文件
*
* @author 小鑫
*
*/
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
Socket s = new Socket("192.168.100.15", 1357);
// 键盘录入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 封装通道输出流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
//一次读取一行
String line=null;
while((line=br.readLine())!=null){
//自定义结束标记
if("over".equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
s.close();
}
}
package org.westos_09_TCP协议键盘录入输出文本文件;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建Socket对象
ServerSocket ss = new ServerSocket(1357);
// 监听客户端
Socket s = ss.accept();
// 获取通道输入流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 服务器输出一个文本文件
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
String line=null;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
s.close();
bw.close();
}
}
5、客户端一个文本文件,服务器端将客户端文本文件中的内容展示到控制台上
package org.westos_10_TCP协议客户端文本文件服务器端输出;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 客户端一个文本文件,服务器端将客户端文本文件中的内容展示到控制台上
*
* @author 小鑫
*
*/
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 创建Socket对象
Socket s = new Socket("192.168.100.15", 4567);
// 封装文件
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
// 获取通道输出流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
String line=null;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
br.close();
s.close();
}
}
package org.westos_10_TCP协议客户端文本文件服务器端输出;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建服务器端Socket对象
ServerSocket ss = new ServerSocket(4567);
// 监听客户端
Socket s = ss.accept();
// 获取通道输入流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
//一次读取一行
String line=null;
while((line=br.readLine())!=null){
System.out.println(line);
}
s.close();
}
}
6、客户端发送文本文件,服务器端复制到文本文件中
package org.westos_01_TCP协议客户端文本文件服务器端复制到另一文本文件;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class UploadClient {
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
Socket s = new Socket("192.168.100.15", 3456);
// 封装文件
BufferedReader br = new BufferedReader(
new FileReader("ClientDemo.java"));
// 获取通道输出流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
String line=null;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
s.close();
br.close();
}
}
package org.westos_01_TCP协议客户端文本文件服务器端复制到另一文本文件;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class UploadClient {
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
Socket s = new Socket("192.168.100.15", 3456);
// 封装文件
BufferedReader br = new BufferedReader(
new FileReader("ClientDemo.java"));
// 获取通道输出流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
String line=null;
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
s.close();
br.close();
}
}
7、客户端发送文本文件,服务器端将文本文件中的内容复制输出到一个新的文本文件中, 并反馈
package org.westos_02_TCP协议客户端文本文件服务器端复制文本文件并反馈;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/**
* 客户端文本文件,服务器端将文本文件中的内容复制输出到一个新的文本文件中, 并且服务器端反馈给客户端,文件复制成功了... public void
* shutdownOutput() throws IOException禁用此套接字的输出流
*
* @author 小鑫
*
*/
public class UploadClient {
public static void main(String[] args) throws IOException {
// 创建Socket对象
Socket s = new Socket("192.168.100.15", 6666);
// 封装数据源
BufferedReader br = new BufferedReader(
new FileReader("ClientDemo.java"));
// 获取通道输出流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
// 读完了反馈
s.shutdownOutput();
// 获取通道输入流读取服务器反馈
BufferedReader brClient = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String fk = br.readLine();
System.out.println(fk);
//释放资源
s.close();
br.close();
}
}
package org.westos_02_TCP协议客户端文本文件服务器端复制文本文件并反馈;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
public static void main(String[] args) throws IOException {
// 创建Socket对象
ServerSocket ss = new ServerSocket(6666);
// 监听客户端
Socket s = ss.accept();
// 获取通道输入流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 文本复制
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy2.java"));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
// 反馈,获取通道内输出流对象
BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
bw.write("文件复制完了");
bw.newLine();
bw.flush();
//关闭资源
s.close();
bw.close();
}
}
8、客户端的图片文件,服务器端输出一个图片文件并且给出反馈
package org.westos_03_TCP协议客户端发送图片服务器并反馈;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 客户端的图片文件,服务器端输出一个图片文件并且给出反馈
*
* @author 小鑫
*
*/
public class UploadClient {
public static void main(String[] args) throws IOException {
// 创建客户端Socket对象
Socket s = new Socket("192.168.100.15", 7777);
// 封装文件,字节流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
"林青霞.jpg"));
// 获取通道内的输出流
BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
//一次读取一个字节数组
byte[] bys=new byte[1024];
int len=0;
while((len=bis.read(bys))!=-1){
bos.write(bys, 0, len);
bos.flush();
}
//客户端告诉服务器端没数据了,别读了
s.shutdownOutput();
//读取服务器的反馈
InputStream is = s.getInputStream();
byte[] bys2=new byte[1024];
int len2=is.read(bys2);
System.out.println(new String(bys2, 0, len2));
//关闭
s.close();
bis.close();
}
}
package org.westos_02_TCP协议客户端文本文件服务器端复制文本文件并反馈;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
public static void main(String[] args) throws IOException {
// 创建Socket对象
ServerSocket ss = new ServerSocket(6666);
// 监听客户端
Socket s = ss.accept();
// 获取通道输入流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 文本复制
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy2.java"));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
// 反馈,获取通道内输出流对象
BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(
s.getOutputStream()));
bw.write("文件复制完了");
bw.newLine();
bw.flush();
//关闭资源
s.close();
bw.close();
}
}
day23
反射机制
反射机制:
反射就是通过获取到该类的字节码文件对象—->Class类对象,通过Class类对象获取该类里面的一些属性(成员变量),构造方法,成员方法等。
面试题:如何获取类的字节码文件对象,并且有几种方式呢?
* 1)Object类中的getClass()方法,表示正在运行的那个类:Class类
* 2)数据类型的class属性 举例:String.class,Student.class
* 3)Class类中的特有方法: public static Class
package org.westos_04_反射机制;
public class Person {
private String name;
int age;
public String address;
//无参构造
public Person(){}
//私有化构造方法
private Person(String name){
this.name=name;
}
//有参构造
Person(String name,int age){
this.name = name ;
this.age = age ;
}
public Person(String name,int age,String address){
this.name = name ;
this.age =age ;
this.address = address ;
}
//成员方法
public void show(){
System.out.println("show");
}
public void method(String s){
System.out.println("method"+s);
}
public String getString(String s, int i) {
return s + "---" + i;
}
private void function(){
System.out.println("function");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address
+ "]";
}
}
2、反射的三种表现形式
package org.westos_04_反射机制;
/**
* 反射机制: 反射就是通过获取到该类的字节码文件对象---->Class类对象,
* 通过Class类对象获取该类里面的一些属性(成员变量),构造方法,成员方法:
* @author 小鑫
*
*/
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException {
// 第一种方式:
// 创建Person对象
Person p1 = new Person();
Class c1 = p1.getClass();// ---->得到Person.class字节码文件对象
Person p2 = new Person();
Class c2 = p2.getClass();// ------->Person.class字节码文件对象
System.out.println(p1 == p2);// false
System.out.println(c1 == c2);// true
// 第二种方式
Class c3 = Person.class;
System.out.println(c3 == c1);// true
// 第三种方式
//参数需要类路径:类的全路径名称
Class c4 = Class.forName("org.westos_04_反射机制.Person");
System.out.println(c4==c1);//true
}
}
3、获取构造方法
package org.westos_05_反射机制_获取成员方法;
import java.lang.reflect.Constructor;
/**
* org.westos_04_反射机制
* @author 小鑫
*
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception {
//获取一个类中的构造方法,首先找到这个类的class文件对象,通过反射
Class c = Class.forName("org.westos_04_反射机制.Person");
//使用该Class类对象中的一些成员方法:
//public Constructor<?>[] getConstructors(),返回的是一个构造方法所在数组
//public Constructor<?>[] getDeclaredConstructors():获取的是当前字节码文件对象中所有的构造方法
Constructor[] con1 = c.getConstructors();
for(Constructor constructor1:con1){
System.out.println(constructor1);
//public org.westos_04_反射机制.Person(java.lang.String,int,java.lang.String)
//public org.westos_04_反射机制.Person()
}
//获取当前Pereson类中所有的构造方法
Constructor[] con2 = c.getDeclaredConstructors();
for(Constructor constructor2:con2){
System.out.println(constructor2);
//public org.westos_04_反射机制.Person(java.lang.String,int,java.lang.String)
//org.westos_04_反射机制.Person(java.lang.String,int)
//private org.westos_04_反射机制.Person(java.lang.String)
//public org.westos_04_反射机制.Person()
}
//获取单个的构造方法:public Constructor<T> getConstructor(Class<?>... parameterTypes)
//返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法
//参数表示:参数数据类型的字节码文件对象:获取指定构造方法里面有参数,需要写上数据类型的字节码文件对象
//获取构造器对象:Constructor
Constructor con3 = c.getConstructor();
//public T newInstance(Object... initargs):传递的是实际参数
Object obj = con3.newInstance();
System.out.println(obj);//Person [name=null, age=0, address=null]
}
}
4、 通过反射获取构造方法并且给成员属性赋值
package org.westos_05_反射机制_获取成员方法;
import java.lang.reflect.Constructor;
/**
* 通过反射获取构造方法并且给成员属性赋值
*
* @author 小鑫
*
*/
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
// 获取Person类的字节码文件对象
Class c = Class.forName("org.westos_04_反射机制.Person");
// 通过反射获取指定构造方法:getConstructor(Class ...parameterTyps) 参数:参数类型.class
Constructor con = c.getConstructor(String.class, int.class,
String.class);
//创建构造器的实例对象,来给他指定的字节码文件对象里面的成员变量赋值
Object obj = con.newInstance("张三",30,"南海");
System.out.println(obj);
//Person [name=张三, age=30, address=南海]
}
}
5、通过反射获取私有的构造方法,并使用
package org.westos_05_反射机制_获取成员方法;
import java.lang.reflect.Constructor;
/**
* 通过反射获取私有的构造方法,并使用
* @author 小鑫
*
*/
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
//1)获取Person类的字节码文件对象
Class c = Class.forName("org.westos_04_反射机制.Person");
//2)获取私有方法
//该方法获取当前指定的公共的构造方法
//public Constructor<T> getConstructor(Class<?>... parameterTypes)
//表示获取类或者接口中的指定的构造方法
//public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
Constructor con = c.getDeclaredConstructor(String.class);
//public void setAccessible(boolean flag):在访问的时候取消java语言访问检查(强制性)
//将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查
con.setAccessible(true);
Object obj = con.newInstance("张三");
System.out.println(obj);
//Person [name=张三, age=0, address=null]
}
}
6、反射获取成员变量并使用:Field
package org.westos_05_反射机制_获取成员方法;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/**
* 通过反射获取成员变量并使用:Field
* Declared:反射私有的成员变量,成员方法,类的关键字
* @author 小鑫
*
*/
public class ReflectDemo4 {
public static void main(String[] args) throws Exception {
//1)通过反射获取字节码文件对象
Class c = Class.forName("org.westos_04_反射机制.Person");
//2)获取所有的公共的成员变量
//public Field[] getFields():所有的公共的可访问的字段,返回的是Field对象数组
//public Field[] getDeclaredFields():获取当前字节码文件对象中所有的公共的或者私有的字段
Field[] fields = c.getFields();
Field[] declaredFields = c.getDeclaredFields();
for(Field f:fields){
System.out.println(f);
//public java.lang.String org.westos_04_反射机制.Person.address
}
//赋值
//获取构造器对象
Constructor con = c.getConstructor();
//构建构造器实例
Object obj = con.newInstance();
System.out.println(obj);
//Person [name=null, age=0, address=null]
//给address赋值并使用
//public Field getField(String name):获取公共的指定的字段 参数为当前成员变量名称"address"
Field addressField = c.getField("address");
//将指定对象变量上此 Field 对象表示的字段设置为指定的新值public void set(Object obj, Object value)
//给obj实例对象里面的成员变量设置一个实际参数---->value
addressField.set(obj, "北京");
System.out.println(obj);//Person [name=null, age=0, address=北京]
//给name赋值并使用
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true);//取消Java语言访问检查
nameField.set(obj, "张三");
System.out.println(obj);//Person [name=张三, age=0, address=北京]
//给age赋值并使用
Field ageField = c.getDeclaredField("age");
ageField.setAccessible(true);//取消Java语言访问检查
ageField.set(obj, 30);
System.out.println(obj);//Person [name=张三, age=30, address=北京]
}
}
7、通过反射获取成员变量并使用
package org.westos_05_反射机制_获取成员方法;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* 通过反射获取成员变量并使用
*
* @author 小鑫
*
*/
public class ReflectDemo5 {
public static void main(String[] args) throws Exception {
// 通过反射获取字节码文件对象并使用
Class c = Class.forName("org.westos_04_反射机制.Person");
/*// 获取成员方法(Method)
// public Method[] getMethods():获取当前该字节码文件对象(Person.class)中自己本身以及它父类中所有的公共成员方法
Method[] methods = c.getMethods() ;
// public Method[] getDeclaredMethods():获取当前字节码文件对象本身所有的成员方法
Method[] methods2 = c.getDeclaredMethods() ;
for(Method m :methods2){
System.out.println(m);
}*/
//获取构造器对象,通过构造器创建当前字节码文件的实例对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();//Person对象
//获取单个方法
//public void show() {}
/**
* public Method getMethod(String name,Class<?>... parameterTypes):指定公共成员方法
* 参数1:表示方法名
* 参数2:该方法的参数类型的Class对象(数据类型的class属性) String.class
*/
Method m1 = c.getMethod("show");
/**
* public Object invoke(Object obj, Object... args)
* 参数1:表示当前针对哪个以实例对象进行方法的调用
* 参数2:当前调用该方法的时候里面传递的实际参数
*/
m1.invoke(obj);
//public void method(String s){}
Method m2 = c.getMethod("method", String.class);
m2.invoke(obj, "nihao");
/**
* public String getString(String s, int i) {
return s + "---" + i;
}
*/
Method m3 = c.getMethod("getString", String.class,int.class);
String objString =(String) m3.invoke(obj, "hello",10);
// private void function(){
// System.out.println("function");
// }
//该方法是私有的,public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
Method m4 = c.getDeclaredMethod("function");
m4.setAccessible(true);//取消Java语言访问检查
m4.invoke(obj);
}
}
8、用户操作
package org.westos_06_handler;
/**
* 用户测试类
* @author 小鑫
*
*/
public class UserDaoDemo {
public static void main(String[] args) {
//创建用户操作对象
UserDao ud = new UserDaoImpl1();
ud.add();
ud.delete();
ud.update();
ud.serach();
System.out.println("-----------");
UserDao ud2 = new UserDaoImpl2() ;
ud2.add() ;
ud2.delete() ;
ud2.update() ;
ud2.serach() ;
}
}
package org.westos_06_handler;
//用户操作接口
public interface UserDao {
// 增
public abstract void add();
// 删
public abstract void delete();
// update:修改
public abstract void update();
// 查
public abstract void serach();
}
package org.westos_06_handler;
public class UserDaoImpl1 implements UserDao {
@Override
public void add() {
System.out.println("增加功能");
}
@Override
public void delete() {
System.out.println("删除功能");
}
@Override
public void update() {
System.out.println("修改功能");
}
@Override
public void serach() {
System.out.println("查询功能");
}
}
package org.westos_06_handler;
public class UserDaoImpl2 implements UserDao {
@Override
public void add() {
System.out.println("权限校验");
System.out.println("添加功能");
System.out.println("日志记录");
}
@Override
public void delete() {
System.out.println("权限校验");
System.out.println("添加功能");
System.out.println("日志记录");
}
@Override
public void update() {
System.out.println("权限校验");
System.out.println("添加功能");
System.out.println("日志记录");
}
@Override
public void serach() {
System.out.println("权限校验");
System.out.println("添加功能");
System.out.println("日志记录");
}
}
9、代理对象
package org.westos_06_handler2;
import java.lang.reflect.Proxy;
public class UserTest {
public static void main(String[] args) {
// 创建用户操作的对象
UserDao ud = new UserDaoImpl();
ud.add();
ud.delete();
ud.update();
ud.serach();
// 给ud对象设置代理对象
// Proxy类中的方法创建动态代理类对象
// public static Object newProxyInstance
// (ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
// InvocationHandler是代理对象需要实现的接口---->需要自定义一个类实现这个接口
// 创建代理对象
MyInvocation handle = new MyInvocation(ud);
UserDao proxy = (UserDao) Proxy.newProxyInstance(ud.getClass()
.getClassLoader(), ud.getClass().getInterfaces(), handle);
//参数1:需要类加载器:首先获取当前目标对象的字节码文件对象,在去调用getClassLoser()
//参数2:获取目标的字节码文件对象,调用方法得到给目标对象提供一组接口
proxy.add();
proxy.delete() ;
proxy.update() ;
proxy.serach() ;
}
}
package org.westos_06_handler2;
//用户操作的接口
public interface UserDao {
//增
public abstract void add() ;
//删
public abstract void delete() ;
//update:修改
public abstract void update() ;
//查
public abstract void serach() ;
}
package org.westos_06_handler2;
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("增加功能");
}
@Override
public void delete() {
System.out.println("删除功能");
}
@Override
public void update() {
System.out.println("修改功能");
}
@Override
public void serach() {
System.out.println("查询功能");
}
}
package org.westos_06_handler2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocation implements InvocationHandler{
//目标对象
private Object target;
//无参构造
public MyInvocation(Object target) {
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("权限校验");
Object result = method.invoke(target, args);
System.out.println("日志记录");
return result;//返回值就是代理对象
}
}
10、反射的应用:集中中添加元素
package org.westos_07_test;
import java.lang.reflect.Method;
import java.util.ArrayList;
/**
* ArrayList<Integer>的一个对象,在这个集合中添加一个字符串数据
* @author 小鑫
*
*/
public class ArrayListTest {
public static void main(String[] args) throws Exception {
ArrayList<Integer> array = new ArrayList<Integer>();
//利用反射类来给集合中添加字符串数据
array.add(100);
Class c = array.getClass();
Method m = c.getMethod("add", Object.class);
m.invoke(array, "hello");
m.invoke(array, "world");
m.invoke(array, "java");
System.out.println(array);
//[100, hello, world, java]
}
}