1.package org.westos_01;
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException;
/**
•将UDP编程的发送端和接收端优化! / public class SendDemo {
public static void main(String[] args) throws IOException { //创建发送端的Socket对象 DatagramSocket ds = new DatagramSocket() ;
//创建数据报包对象 byte[] bys = "hello,udp,我来了".getBytes() ; DatagramPacket dp = new DatagramPacket(bys, bys.length,InetAddress.getByName("192.168.10.1"),12345) ;
//发送数据 ds.send(dp);
//释放资源
ds.close();
} }
package org.westos_01;
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket;
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//创建接收端的Socket对象
DatagramSocket ds = new DatagramSocket(12345) ;
//创建接收容器
//创建字节数组的大小1024或者1024的倍数
byte[] bys = new byte[1024] ;
DatagramPacket dp = new DatagramPacket(bys, bys.length);
//调用接收的方法
ds.receive(dp);//阻塞式方法
//解析数据,将数据展示在控制台
//获取ip地址
String ip = dp.getAddress().getHostAddress() ;
//public byte[] getData() 获取缓冲区中实际的字节数
//public int getLength() 获取缓冲区中实际的长度
String s = new String(dp.getData(), 0,dp.getLength()) ;
//展示控制台
System.out.println("from"+ip+"data is:"+s);
//释放资源
ds.close();
}
}
2.可以发送多次,联系多线程
package org.westos_02;
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress;
/*
•需求: 将发送端的数据变方式,并且多次发送 • • •多线程: •Runable接口的方式 •SendThread implements Runnable{ •} •发送端的线程 •接收端的线程 • •主线程 •只需要需一个窗口
•*/ public class SendDemo {
public static void main(String[] args) {
try { // 创建Socket对象 DatagramSocket ds = new DatagramSocket();
// 键盘录入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null ; //读了一次
while((line=br.readLine())!=null){
//自定义结束条件
if("886".equals(line)) {
break ;
}
byte[] bys = line.getBytes() ;
int length = bys.length ;
// 创建数据报包
DatagramPacket dp = new DatagramPacket(bys,length,
InetAddress.getByName("192.168.10.1"), 10086);
// 发送数据
ds.send(dp);
}
// 释放资源
ds.close();
} catch (IOException e) { e.printStackTrace(); }
} }
package org.westos_02;
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket;
public class ReceiveDemo {
public static void main(String[] args) {
try {
//创建接收端的Socket对象
DatagramSocket ds = new DatagramSocket(10086);
while(true) {
//需要创建接收容器
byte[] bys = new byte[1024] ;
DatagramPacket dp = new DatagramPacket(bys, bys.length) ;
//接收
ds.receive(dp);
//解析数据
String ip = dp.getAddress().getHostAddress() ;
String s = new String(dp.getData(), 0, dp.getLength()) ;
System.out.println("from" +ip +"data is:"+s);
//释放资源,接收端不停地接收数据,所以不应该该关闭
// ds.close(); }
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.简单的聊天室
发送端 package org.westos_03;
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 { //使用字符缓冲输入流 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.10.1"), 10086) ;
//发送数据
ds.send(dp);
}
//释放
ds.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
接收端
package org.westos_03;
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);
//解析数据
String ip = dp.getAddress().getHostAddress() ;
String s = new String(dp.getData(), 0, dp.getLength()) ;
System.out.println("from" +ip +"data is:"+s);
//释放资源,接收端不停地接收数据,所以不应该该关闭
// ds.close(); } }catch(IOException e) { e.printStackTrace(); } }
}
package org.westos_03;
import java.net.DatagramSocket; import java.net.SocketException;
/ 多线程: •Runable接口的方式 •SendThread implements Runnable{ •} •发送端的线程 •接收端的线程 • •主线程 •只需要需一个窗口 ,让我们不断发送数据 •
•*简单的聊天室
• •项目的聊天室 集合+多线程+IO流+网络编程 综合应用 •1)公聊 •2)私聊 •3)在线人数 •4)发送文件
•5)下线提醒 */ public class ChartRoom {
public static void main(String[] args) throws Exception {
//分别创建发送端和接收端的Socket对象 DatagramSocket sendSocket = new DatagramSocket() ; DatagramSocket receiveSocket = new DatagramSocket(10086) ;
//创建资源对象 SendThread st = new SendThread(sendSocket) ; ReceiveThread rt = new ReceiveThread(receiveSocket) ;
//创建线程对象 Thread t1 = new Thread(st) ; Thread t2 = new Thread(rt) ;
//启动线程 t1.start(); t2.start();
} }
4.Tcp
package org.westos_04;
import java.io.OutputStream; import java.net.Socket;
/* TCP(建立连接通道)编程的客户端的开发步骤 1)创建客户端的Socket对象
•Socket:就是客户端的Socket •构造方法 •public Socket(InetAddress address, int port)
•public Socket(String host, int port):创建客户端套接字对象,并且指定端口号和ip文本形式 2)获取通道内的输出流对象 3)给服务器端写数据 4)释放资源 java.net.ConnectException: Connection refused: connect 连接被拒绝 不要先运行客户端,客户端的连接需要服务器监听到才能连接 / public class ClientDemo {
public static void main(String[] args) throws Exception { //1)创建客户端的Socket对象 //public Socket(String host, int port) Socket s = new Socket("192.168.10.1", 12306) ; //2)获取通道内的输出流对象 // public OutputStream getOutputStream():获取套接字 的输出流 OutputStream out = s.getOutputStream() ; //3)给服务器端写数据 过去 out.write("hello,Tcp,我来了".getBytes());
//释放资源 s.close();
} }
package org.westos_04;
import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;
/**
•*服务端的开发步骤:
•1)创建服务器端的Socket对象 •2)监听客户端的连接(阻塞方法) •3)获取通道内的输入流 •4)读取数据,显示控制台 •5)释放资源
•ava.net.BindException: Address already in use: JVM_Bind 地址被绑定,因为已经有服务器在监听客户端连接 / public class ServerDemo {
public static void main(String[] args) throws Exception { // 1)创建服务器端的Socket对象 // public ServerSocket(int port) throws IOException创建绑定到特定端口的服务器套接字 ServerSocket ss = new ServerSocket(12306) ;
//2)监听客户端的连接(阻塞方法)
// public Socket accept(): throws IOException侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞 Socket s = ss.accept() ; // 3)获取通道内的输入流 // InputStream getInputStream()
InputStream in = s.getInputStream() ;
// 4)读取数据,显示控制台 //获取ip文本形式' // public InetAddress getInetAddress() String ip = s.getInetAddress().getHostAddress() ; byte[] bys = new byte[1024] ; int len = in.read(bys) ; String data = new String(bys, 0, len) ; System.out.println("from" +ip +"data is :"+data); // 5)释放资源 s.close(); // ss.close(); 服务端可以不关闭
} }
5.Tcp带反馈
package org.westos_05;
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建客户端的Socket对象
Socket s = new Socket("192.168.10.1",10011) ;
//获取通道内的流 发哦少年宫数据
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_05;
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 {
//创建服务器端的Socket对象
ServerSocket ss = new ServerSocket(10011);
//监听客户端连接
Socket s = ss.accept() ;
//服务器端获取通道内的输入流,读取数据
InputStream in = s.getInputStream() ;
byte[] bys =new byte[1024] ;
int len = in.read(bys) ;
System.out.println(new String(bys, 0, len));
//服务器端给客户端反馈
//获取通道内的输出流
OutputStream out = s.getOutputStream() ;
out.write("数据已经收到".getBytes());
//服务器端不需要关闭
s.close();
}
} 6.package org.westos_07;
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 Administrator • •客户端读取文本文件,服务器端将数据输出在控制台上
•*/ public class ClientTest {
public static void main(String[] args) throws IOException {
//有客户端Socket对象.指定ip和端口号 Socket s = new Socket("192.168.10.1", 23456) ;
//使用流的形式录入数据 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_07;
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 ServerTest {
public static void main(String[] args) throws IOException {
//必须创建服务器端Socket
ServerSocket ss = new ServerSocket(23456) ;
//监听
Socket s = ss.accept() ;
//封装通道内的流
BufferedReader br =
new BufferedReader(
new InputStreamReader(s.getInputStream())) ;
//封装一个文本文件
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt")) ;
String line = null ;
while((line=br.readLine())!=null) {
//边获取数据,并且同时将数据写到bw.txt文件中
bw.write(line);
bw.newLine();
bw.flush();
}
//关闭资源
// br.close(); s.close(); bw.close(); } }
7.反馈的问题(shutdownOutput();)
package org.westos_10;
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; import java.net.UnknownHostException;
//客户端读取当前项目下的某个文本文件,服务器复制这个文件内容输出一个新的文本文件(Copy.java) /** •按照正常的思路,加入了服务器端反馈操作,发现服务器端的反馈数据,客户端并没有收到,客户端也没有结束,再等待服务器发送 • •在客户端这边,如果SendDemo.java如果读完了,服务器端那边并不知道是否读完(流是不能使用null作为信息结束条件的,但是客户端文本文件是可以用null作为信息结束条件的) •服务器等待客户端通知文本已经读完了,而客户端还需要服务器端反馈 • •解决方案: •1)客户端这边,写一个结束条件,---->服务器如果读取到了这个结束条件的话,服务器就可以反馈 •第一种方式虽然可以解决这种问题,不好,不灵活! •2)public void shutdownOutput():通知服务器端(我没有数据了,你赶紧反馈) •@author Administrator
•*/ public class UploadClient {
public static void main(String[] args) throws IOException {
//创建客户端的Socket对象 Socket s = new Socket("192.168.10.1",11111); //当前对象创建之后,就会和服务器端建立连接通道
//封装文本文件 BufferedReader br = new BufferedReader( new FileReader("SendDemo.java")) ;
//封装通道内的流 BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(s.getOutputStream())) ; //读写操作 String line =null; while((line=br.readLine())!=null) { bw.write(line); bw.newLine(); bw.flush(); }
//自定义的结束条件 /bw.write("over"); bw.newLine(); bw.flush();/
//通知服务器端,客户端的文件已经完了,赶紧给反馈 //public void shutdownOutput(): s.shutdownOutput();
//获取服务器反馈的数据 //获取通道内的字符输入流 BufferedReader brClient = new BufferedReader( new InputStreamReader(s.getInputStream())) ; String client = brClient.readLine() ; System.out.println(client);
//释放资源 br.close(); s.close();
} }
package org.westos_10;
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;
//客户端将文本文件中的数据,复制到服务器端输出的新的java文件中,然后服务器端要给客户端反馈数据,客户端将反馈的数据展示 public class UploadServer {
public static void main(String[] args) throws IOException {
//服务器端的Socket对象
ServerSocket ss = new ServerSocket(11111) ;
//监听
Socket s = ss.accept() ;//阻塞
//封装通道内的流
BufferedReader br = new BufferedReader(
new InputStreamReader(s.getInputStream())) ;
//封装最终要输出的文本文件
BufferedWriter bw= new BufferedWriter(new FileWriter("Copy.java")) ;
String line = null ;
while((line=br.readLine())!=null) { //阻塞 //通道内的流结束不是用null作为结束条件的
/*if("over".equals(line)) {//让服务器读到这个结束条件
break ;
}*/
bw.write(line);
bw.newLine();
bw.flush();
}
//服务端获取通道内的输出流对象
BufferedWriter bwServer = new BufferedWriter(
new OutputStreamWriter(s.getOutputStream())) ;
//向客户端反馈
bwServer.write("文件上传成功了");
bwServer.newLine();
bwServer.flush();
//释放资源
bw.close();
s.close();
}
}
8.图片的传送(字节流运用的flush()强制刷新未加载的图片)
package org.westos._11;
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.Socket;
/* 客户端读取当前项目下的该图片文件,服务器端将文件的内容复制,输出一个新的图片文件:mm.jpg (服务器加上反馈)
/ public class UploadClient {
public static void main(String[] args) throws IOException {
//创建Socket对象
Socket s = new Socket("192.168.10.1", 19191);
//封装图片文件
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);
//public void flush()
// throws IOException刷新此输出流并强制写出所有缓冲的输出字节
bos.flush();
}
//通知对方,数据已经完了
s.shutdownOutput();
//获取服务器端的反馈数据
//获取通道内的输入流对象
InputStream is = s.getInputStream() ;
byte[] buffer = new byte[1024] ;
int len2 = is.read(buffer) ;
String data = new String(buffer, 0, len2) ;
System.out.println(data);
//释放资源
s.close();
bis.close();
}
}
package org.westos._11;
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;
public class UploadServer {
public static void main(String[] args) throws IOException {
//创建Socket对象
ServerSocket ss = new ServerSocket(19191);
//监听
Socket s = ss.accept() ;
//封装通道内的流
BufferedInputStream bis = new BufferedInputStream(
s.getInputStream()) ;
//封装图片文件
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("mm.jpg")) ;
//复制
byte[] bys = new byte[1024] ;
int len = 0 ;
while((len=bis.read(bys))!=-1) {
bos.write(bys, 0, len);
//强制刷新缓冲区所有的字节数,防止出现图片不全
bos.flush();
}
//服务器反馈数据
//获取通道内的输出流
OutputStream out = s.getOutputStream() ;
out.write("图片上传成功了...".getBytes());
//释放资源
bos.close();
s.close();
}
}
什么是反射? 反射就是通过获取class字节码文件对象/Class的类对象, 获取该字节码文件对象中的成员变量,构造方法,和成员方法
Field: 简称成员变量 (Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。 反射的字段可能是一个类(静态)字段或实例字段。) Constructor:简称构造方法:提供关于类的单个构造方法的信息以及对它的访问权限。 Method:简称成员方法:类或接口上单独某个方法(以及如何访问该方法)的信息
10.面试题: 如何获取class字节码文件对象/Class的类对象 三种方式来获取这个class字节码文件对象: 1)Object中的getClass() 2)任何数据类型的静态属性class 3)Class类中的方法: forName(String className) forName("类路径")
如果你自己玩,任意:第一种和第二种都可以
但是,开发中使用第三种方式,forName方法中的参数是一个String类型,以后可以用字符串类型数据作为配置文件!
11.代理: 在程序的执行过程中,通过一个类Proxy和接口invacationHandler(处理程序)实现动态代理
Proxy类中的方法创建动态代理类对象 public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 最终会调用InvocationHandler的方法 InvocationHandler Object invoke(Object proxy,Method method,Object[] args)
参数1:loader:类加载器 public ClassLoader getClassLoader() 参数2:public Class<?>[]
12代理的概念
程序中的代理:
1. 要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如异常处理、日志、计算方法 的运行时间、事物管理等等
2. 编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加 上系统能耐的代码
3. 如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标 类还是代理类,这样以后很容易切换,譬如,想要日志功能时就配置代理类,否则配置目标类,这样,增加系统 功能很容易,以后运行一段时间后,又想去掉系统功能也很容易
交叉业务编程问题即为面向方面的编程(Aspect Oriented Program,简称AOP)。AOP的目标就是要使交叉业务 模块化,可以采用将切面代码移动到原始方法的周围。这与直接在方法中编写切面代码的运行效果是一样的。
13.代理的作用
动态代理技术:
1.要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部写成静态代理方式,将是一件非常麻烦的事情!写成百上千个代理类,是不是太类了
2.JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
3.JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
4.CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。
5.代理类的各个方法中通常除了要调用目标的相应的方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置上加上系统功能代码:
-
在调用目标方法之前
-
在调用目标方法之后
-
在调用目标方法前后
-
在处理目标方法异常的catch块中