Java学习|黑马笔记|Day23】网络编程、反射、动态代理
【DAY23】
文章目录
-
- 【DAY23】
-
- 一.网络编程
-
- 1)三要素
- 1.1)IP
- InetAddress类的使用
- 1.2)端口号
- 1.3)协议
- 2.1)UDP协议发送数据
- 2.2)UDP协议接收数据
- 2.3)UDP的三种通信方式
- 3.1)TCP协议的发送和接收
- 3.2)中文乱码问题
- 3.3)三次握手四次挥手
- 二.反射
-
- 1)概述
- 2)获取class对象的三种方式
- 3)反射获取构造方法
- 4)反射获取成员变量
- 5)反射获取成员方法
- 三.动态代理
一.网络编程
在通信协议下不同计算机上运行的程序,进行的数据传输
应用场景:计算机跟计算机之间通过网络
Java中使用java.net包下的技术轻松开发出常见的网络应用程序
常见的软件架构:
- CS:Client/Server 在用户本地需要下载并安装客户端程序,在远程有一个服务端程序 eg:QQ
- 优点:画面精美,用户体验好
- 缺点:需要开发客户端也需要开发服务端。用户需要下载和更新
- BS:Browser/Server 只需要一个浏览器,用户通过不同网址,客户访问不同的服务器 eg:淘宝
- 优点:不需要开发客户端,只需要页面+服务端,用户不需要下载打卡浏览器就能使用
- 缺点:如果应用过大,用户体验受到影响
1)三要素
IP:设备在网络中的地址,是唯一的表示
端口号:应用程序在设备中的唯一表示
协议:数据在网络中传输的规则,常见的协议有UDP,TCP,http,ftp
1.1)IP
互联网协议地址,上网设备在网络中的地址是分配给上网设备的数字标签
分类:
-
IPv4互联网通信协议第四版
采用32位地址长度,分为4组,最多只有2^32个IP,2019年11.26全部分配完毕
可以用局域网解决IP不够的问题
-
IPv6互联网通信协议第六版
采用128位地址长度,分为8组 ,最多有2^128个IP
IPv4的细节
1.分类:公网地址(万维网使用)和私有地址(区域网使用)
192.168开头的就是私有地址,范围为192.168.0.0—192.168.255.255,专门为组织机构内部使用
2.特殊IP地址:127.0.0.1,也可以是localhost:是回送地址也称本地回送地址,也称本机IP,永远只会寻找当前所在本机
常用的CMD
- ipconfig:查看本机IP地址
- ping:检查网络是否连通
InetAddress类的使用
表示IP地址
public class t1 { public static void main(String[] args) throws UnknownHostException { //1.获取InetAddress的对象 InetAddress address = InetAddress.getByName(\"LAPTOP-K3EOH2DK\");//\"设备名\" System.out.println(address);//LAPTOP-K3EOH2DK/192.168.1.32 String name = address.getHostName(); System.out.println(name);//LAPTOP-K3EOH2DK String ip = address.getHostAddress(); System.out.println(ip);//192.168.1.32 }}
1.2)端口号
应用程序在设备中唯一的标识
有两个字节表示的整数,取值范围:065535,其中01023之间的端口号用于一些知名的网络访问或者应用
一个端口号只能被一个应用程序使用
1.3)协议
计算机网络中连接和通信的规则被称为网络通信协议
- OSI参考模型:世界互联协议标准,全球通信规范,单模型过于理想化,未能在因特网上进行广泛推广
- TCP/IP参考模型(或TCP/IP协议):事实上的国际标准
UDP协议:
- 用户数据报协议
- UDP是面向无连接通信协议,速度快,有大小限制一次最多发送64K,数据不安全,易丢失数据
TCP协议:
- 传输控制协议
- TCP是面向连接通信协议,速度慢,没有大小限制,数据安全
2.1)UDP协议发送数据
public class t1 { public static void main(String[] args) throws IOException { //1.创建对象 //绑定端口号,通过这个端口往外发送 //空参:所有可能的端口中随机一个进行使用 //有参:指定端口号进行绑定 DatagramSocket ds = new DatagramSocket(); //2.打包数据 String str = \"你好你好你好你好你好\"; byte[] bytes = str.getBytes(); InetAddress address = InetAddress.getByName(\"192.168.1.32\"); int port = 10086;//端口号 DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port); //3.发送数据 ds.send(dp); //4.释放数据 ds.close(); }}
2.2)UDP协议接收数据
public class T2 { public static void main(String[] args) throws IOException { //1.创建DatagramSocket DatagramSocket ds = new DatagramSocket(10086); //2.接收数据包 byte[] bytes = new byte[1024]; DatagramPacket dp = new DatagramPacket(bytes, bytes.length); ds.receive(dp); //3.解析数据包 byte[] data = dp.getData(); int len = dp.getLength(); InetAddress address = dp.getAddress(); int port = dp.getPort(); System.out.println(\"接收到数据\" + new String(data,0,len)); System.out.println(\"该数据是从\" + address + \"这台电脑中的\" + port + \"这个接口发出的\"); //4.释放数据 ds.close(); }}
先运行接收端再运行发送端
2.3)UDP的三种通信方式
-
单播
一对一
-
组播
一对组
组播地址:224.0.0.0~239.255.255.255 其中224.0.0.0~224.0.0.255为预留的组播地址
-
广播
一对局域网中的所有设备
广播地址:255.255.255.255
组播
public class t1 { public static void main(String[] args) throws IOException { //组播 //1.创建对象 MulticastSocket ms = new MulticastSocket(); //2.打包数据 String str = \"你好你好你好你好你好\"; byte[] bytes = str.getBytes(); InetAddress address = InetAddress.getByName(\"224.0.0.1\"); int port = 10000;//端口号 DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port); //3.发送数据 ms.send(dp); //4.释放数据 ms.close(); }}
public class T2 { public static void main(String[] args) throws IOException { //1.创建对象 MulticastSocket ms = new MulticastSocket(10000); //2.将当前本机添加到224.0.0.1的这一组中 InetAddress adress = InetAddress.getByName(\"224.0.0.1\"); ms.joinGroup(adress); //3.接收数据包 byte[] bytes = new byte[1024]; DatagramPacket dp = new DatagramPacket(bytes, bytes.length); ms.receive(dp); //4.解析数据包 byte[] data = dp.getData(); int len = dp.getLength(); InetAddress address = dp.getAddress(); int port = dp.getPort(); System.out.println(\"接收到数据\" + new String(data,0,len)); System.out.println(\"该数据是从\" + address + \"这台电脑中的\" + port + \"这个接口发出的\"); //5.释放数据 ms.close(); }}
广播
public class t1 { public static void main(String[] args) throws IOException { //组播 //1.创建对象 MulticastSocket ms = new MulticastSocket(); //2.打包数据 String str = \"你好你好你好你好你好\"; byte[] bytes = str.getBytes(); InetAddress address = InetAddress.getByName(\"255.255.255.255\"); int port = 10000;//端口号 DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port); //3.发送数据 ms.send(dp); //4.释放数据 ms.close(); }}
3.1)TCP协议的发送和接收
客户端
-
创建客户端的对象Socket对象(Socket)与自动服务器端连接
Socket(String host,int port)
-
获取输出流,写数据
OutputStream getOutputStream()
-
释放数据
void close()
服务器
-
创建服务器端的Socket对象(ServerSocket)
ServerSocket(int port)
-
监听客户端连接,返回一个Socket对象
Socket accept()
-
获取输入流,读数据,并把数据显示在控制台
InputStream getInputStream()
-
释放资源
void close()
客户端
public class t1 { public static void main(String[] args) throws IOException { //1.创建对象 Socket socket = new Socket(\"192.168.1.32\",10086); //2.从连接通道中获取输出流 OutputStream os = socket.getOutputStream(); //写出数据 os.write(\"你好你好你好你好你好\".getBytes()); //3.释放数据 os.close(); socket.close(); }}
服务端
public class T2 { public static void main(String[] args) throws IOException { //1.创建对象 ServerSocket ss = new ServerSocket(10086); //2.监听客户端的连接 Socket socket = ss.accept(); //3.从连接通道中获取输入流读取数据 InputStream is = socket.getInputStream(); int b; while((b = is.read()) != -1) { System.out.println((char)b); } //4.释放资源 socket.close(); ss.close(); }}
3.2)中文乱码问题
乱码原因:一个中文三个字节,InputStream字节流一个一个字节读所有造成乱码
解决方法:用转换流把字节流转换为字符流
public class T2 { public static void main(String[] args) throws IOException { //1.创建对象 ServerSocket ss = new ServerSocket(10086); //2.监听客户端的连接 Socket socket = ss.accept(); //3.从连接通道中获取输入流读取数据 InputStream is = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(is); int b; while((b = isr.read()) != -1) { System.out.print((char)b); } //4.释放资源 isr.close() socket.close(); ss.close(); }}
3.3)三次握手四次挥手
二.反射
1)概述
反射允许对封装类的字段,方法和构造函数的信息进行编程访问
2)获取class对象的三种方式
-
Class.forName(“全类名”);
最常用
-
类名.class
一般更多是当做参数进行传递
-
类名.getClass();
当已经有了这个类的对象时才能使用
public class t1 { public static void main(String[] args) throws IOException, ClassNotFoundException { //1.法一 //全类名:包名 + 类名 Class clazz1 = Class.forName(\"T1.Student\"); //2.法二 Class clazz2 = Student.class; //3.法三 Student s = new Student(); Class clazz3 = s.getClass(); }}
3)反射获取构造方法
public class t1 { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException { //1.获取class字节码文件对象 Class clazz = Class.forName(\"T1.Student\"); //2.获取构造方法 Constructor[] cons = clazz.getConstructors(); for (Constructor con : cons) { System.out.println(con); } Constructor[] cons2 = clazz.getDeclaredConstructors(); for (Constructor con2 : cons2) { System.out.println(con2); } //获取单个 Constructor con1 = clazz.getDeclaredConstructor(); System.out.println(con1); Constructor con2 = clazz.getDeclaredConstructor(String.class); System.out.println(con2); }}
4)反射获取成员变量
public class t1 { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, NoSuchFieldException { //1.获取class字节码文件对象 Class clazz = Class.forName(\"T1.Student\"); //2.获取成员变量 Field[] fields = clazz.getFields(); for (Field field : fields) { System.out.println(field); } Field[] fields2 = clazz.getDeclaredFields(); for (Field field2 : fields2) { System.out.println(field2); } //获取单个 Field name = clazz.getDeclaredField(\"name\"); //获取权限修饰符 int modifiers = name.getModifiers(); System.out.println(modifiers); }}
5)反射获取成员方法
三.动态代理
特点:无侵入式的给代码增加额外的功能
为什么需要代理对象如果要干的事情太多可以通过代理转移部分职责
代理长什么样对象有什么方法想被代理,代理就一定要有相应的方法