UDP网络通信的发包过程
- 使用DatagramSocket()创建一个数据包套接字。
- 使用DatagramPacket(byte[]buf, int offset, int length, InetAddress address, int port)创建要发送的数据包。
- 使用DatagramSocket类的send()方法数据包
UDP网络通信的收包过程
- 使用DatagramSocket(int)创建一个数据包套接字,绑定到指定的端口。
- 使用DatagramPacket(byte[]buf,int length)创建字节数组来接收数据包.
- 使用DatagramSocket类的receive()方法接收UDP
获取的数据实际上就存储在创建空包的数组种,转换显示时建议设置长度
System.out.println(dp.getLength()); //数据的具体长度
String str=new String(buffer,0,dp.getLength());
一般来说UDP协议的最大数据包的长度64k
多播或者组播的实现
(真正聊天室的实现原理)
-
组播是基于路由器之上实现的,要想网络内支持组播,需要有能够管理组播组的路由器或是三层交换机(带部分路由功能的交换机)。通常在我们的网络中,都会支持组播,即我们的程序可以使用组播技术,视频会议就使用这个技术。
-
IP网络的多播一般通过多播IP地址来实现。多播IP地址就是D类IP地址,即224.0.0.0至239.255.255.255之间的IP地址。通常选择230之后的地址,使用UDP协议,把每个客户端(收端和发端)的socket都加入到这个地址上,之后客户端往这个地址上发送一个消息后,在这个组里的其他客户端都可以监听收到这个消息。
-
在java中,java.net.MulticastSocket具有组播的功能,它是DatagramSocket的子类。MulticastSocket可以将数据报以广播的方式发送给加入指定组的所有客户端
-
组播是指把信息同时传递给一组目的地址。它使用的策略是最高效的,因为消息在每条网络链路上只需传递一次,且只有在链路分叉的时候,消息才会被复制。与多播相比,常规的点到单点传递被称作单播。当以单播的形式把消息传递给多个接收方时,必须向每个接收者都发送一份数据副本。由此产生的多余副本将导致发送方效率低下,且缺乏可扩展性。不过,许多流行的协议——例如XMPP,用限制接收者数量的方法弥补了这一不足
代理服务器的使用
JDK1.5提供了Proxy和ProxySelector类来实现代理访问。
Proxy代表一个代理服务器,可以在打开URLConnection连接时指定代理,也可以在创建Socket连接时指定代理。
ProxySelector是一个代理选择器,提供了对代理服务器更加灵活的控制,可以对http\https\ftp\socket等进行分别设置,还可以设置不需要通过代理服务器的主机和地址
代理服务器的功能:
- 突破自身IP限制
- 提高访问速度
反射
Java反射机制允许程序在运行时透过Reflection APIs取得任意一个已知名称的class的内部信息,包括modifiers(如public、static等)、superclass(如Object)、实现的interfaces(如Serializable)、fields(属性)和methods(方法)(但不包括methods定义),可于运行时改变fields的内容,也可调用methods
优点:
- 在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
缺点:
- 反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射
- 反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题
反射的用途
- 反编译:
.class-->.java
- 通过反射机制访问java对象的属性,方法,构造方法等
- 当在使用IDE,比如Ecplise时,当输入一个对象或者类,并想调用他的属性和方法是,一按点号,编译器就会自动列出他的属性或者方法,这里就是用到反射。
- 反射最重要的用途就是开发各种通用框架。比如很多框架Spring都是配置化的(比如通过XML文件配置Bean),为了保证框架的通用性,可能需要根据配置文件加载不同的类或者对象,调用不同的方法,这个时候就必须使用到反射了,运行时动态加载需要的加载的对象
- MyBatis持久层框架 Spring业务层框架 SpringMVC表现层框架
动态获取类的信息以及动态调用对象的方法称为Java的反射Reflection机制。
反射提供了封装程序集、模块和类型的对象。在Java运行时环境中,对于任意一个类的对象,可以通过反射获取这个类的信息。
Class类是Reflection API中的核心类
主要有以下方法:
-
getName():获取类的名字,例如java.util.Date
-
getFields():获取类中public类型的属性,自定义或者从父类种继承
-
getDeclaredFields():获取类的所有属性(包括public、protected、default、private),只能获取到当前类种定义,不能获取父类继承的
-
getMethods():获取类中public类型的方法
-
getDeclaredMethods():获取类的所有方法
-
getMethod(String name,Class[] parameterTypes):获取类的指定方法,name:指定方法的名字,parameterType:指定方法的参数类型
-
getDeclaredMethod
-
getConstrutors():获取类中public类型的构造方法
-
getDeclaredConstructors()
-
getConstrutor(Class[] parameterTypes):获取类的指定构造方法,parameterTypes:指定构造方法的参数类型
-
getDeclaredConstructor
-
newInstance():通过类的public不带参数的构造方法创建该类的一个对象;
@Deprecated(since=“9”)
注:在访问私有属性和私有方法时,需要对访问的私有属性或方法设置setAccessible(true)使被反射的类抑制java的访问检查机制。否则会报IllegalAccessException异常。
反射的使用
想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节
码文件也就对应着一个Class类型的对象,也就是字节码文件对象。
获取字节码文件对象的三种方式:
- Class clazz1 = Class.forName(“全限定类名”);
通过Class类中的静态方法forName,直接获取到一个类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件 - Class clazz2 = Person.class;
当类被加载成.class文件时,此时Person类变成了.class,在获取该字节码文件对象,也就是获取自己, 该类处于字节码阶段 - Class clazz3 = p.getClass();
通过类的实例获取该类的字节码文件对象,该类处于创建对象阶段
Class.forName和x.class获取类对象的区别
-
处理静态代码块和静态属性
Class<?> clz = Class.forName(“com.yan6.class2.A1”);
System.out.println(clz); -
不会处理静态代码块和静态属性
Class<?> clz2=A1.class;
System.out.println(clz2);
获取类的Class对象
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。获取类的Class对象有4种方式。
- 调用getClass
Boolean var1 = true;Class<?> classType2 = var1.getClass(); System.out.println(classType2);
输出:class java.lang.Boolea
- 运用.class 语法
Class<?> classType4 = Boolean.class; System.out.println(classType4);
输出:class java.lang.Boolean
- 运用静态方法Class.forName()
Class<?> classType5 = Class.forName("java.lang.Boolean"); System.out.println(classType5);
输出:class java.lang.Boolean
- 运用primitive wrapper classes的TYPE语法,这里返回的是原生类型,和Boolean.class返回的不同
Class<?> classType3 = Boolean.TYPE; System.out.println(classType3);
输出:boolean
public static final Class TYPE = (Class) Class.getPrimitiveClass(“boolean”);
获取构造方法
通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例。Class<T>
类提供了几个方法获取类的构造器。
Constructor<T> getConstructor(Class<?>... parameterTypes)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法Constructor<?>[] getConstructors()
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法Constructor<?>[] getDeclaredConstructors()
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。它们是公共、保护、默认(包)访问和私有构造方法
获取类属性
获取类的Fields。可以通过反射机制得到某个类的某个属性,然后改变对应于这个类的某个实例的该属性值。JAVA 的Class<T>
类提供了几个方法获取类的属性。
Field getField(String name)
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段Field[] getFields()
返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段Field getDeclaredField(String name)
返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段Field[] getDeclaredFields()
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段
可见getFields和getDeclaredFields区别:
- getFields返回的是申明为public的属性,包括父类中定义
- getDeclaredFields返回的是指定类定义的所有定义的属性,不包括父类的。
获取类中的方法
通过反射机制得到某个类的某个方法,然后调用对应于这个类的某个实例的该方法。Class类提供了几个方法获取类的方法。
Method getMethod(String name, Class<?>... parameterTypes)
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法Method[] getMethods()
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法Method getDeclaredMethod(Stringname, Class<?>... parameterTypes)
返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法Method[] getDeclaredMethods()
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法
在JDK中,主要由以下类实现Java反射机制:
-
Class类:代表一个类
-
Field类:代表类的成员变量(属性)
-
Method类:代表类的方法
-
Constructor类:代表类的构造方法
-
Array类:提供了动态创建数组,以及访问数组元素的静态方法;
以上类中,Class类在java.lang包,其余位于java.lang.reflect包。
java.lang.Object类(所有类的超类)定义了getClass()方法,任意一个Java对象都可以通过此方法获得它的class。