java高级部分(十)-(UDP聊天室)

UDP多线程聊天室:

   Runable接口的方式

   发送端的线程

public class SendThread implements Runnable {

	private DatagramSocket ds=null;
	
	public SendThread(DatagramSocket ds) {
		super();
		this.ds = ds;
	}

	@Override
	public void run() {
		// TODO 自动生成的方法存根
		try {
			
			while(true) {
				BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
				String line=null;
				while((line=br.readLine())!=null) {
					if("886".equals(line)) {
						break;
					}
					byte[] bs = line.getBytes();
					DatagramPacket dp=new  DatagramPacket(bs, 0, bs.length, InetAddress.getByName("172.21.195.19"), 10086);
					ds.send(dp);
				}
				ds.close();
			}
			
		} catch (Exception e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}

	
}

   接收端的线程

public class ReceiveDemo implements Runnable{

	private DatagramSocket ds=null;
	
	public ReceiveDemo(DatagramSocket ds) {
		super();
		this.ds = ds;
	}

	@Override
	public void run() {
		// TODO 自动生成的方法存根
		while(true) {
			byte [] by=new byte[1024];
			int len=by.length;
			DatagramPacket dp=new DatagramPacket(by, len);
			
			try {
				ds.receive(dp);
				String ip=dp.getAddress().getHostAddress();
				String data=new String(dp.getData(), 0, dp.getLength());
				System.out.println("ip:"+ip+"\n"+"data:"+data);
			} catch (IOException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
		}
	}

}

   主线程

   只需要需一个窗口 ,让我们不断发送数据

 public static void main(String[] args) throws Exception {
	
        	DatagramSocket ds=new DatagramSocket();
        	DatagramSocket dss=new DatagramSocket(10086);
        	
        	SendThread st=new SendThread(ds);
        	ReceiveDemo rd=new ReceiveDemo(dss);
        	
        	Thread t1=new Thread(rd);
        	Thread t2=new Thread(st);
        	t1.start();
        	t2.start();
       }

 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 连接被拒绝

 不要先运行客户端,客户端的连接需要服务器监听到才能连接

服务端的开发步骤:

  1)创建服务器端的Socket对象

  2)监听客户端的连接(阻塞方法)

  3)获取通道内的输入流

  4)读取数据,显示控制台

  5)释放资源

 java.net.BindException: Address already in use: JVM_Bind  地址被绑定,因为已经有服务器在监听客户端连接

 客户端读取当前项目下的某个文本文件,服务器复制这个文件内容输出一个新的文本文件(Copy.java)

  解决等待反馈的方案:

   1)客户端这边,写一个结束条件,---->服务器如果读取到了这个结束条件的话,服务器就可以反馈

   第一种方式虽然可以解决这种问题,不好,不灵活!

   2)public void shutdownOutput():通知服务器端(我没有数据了,你赶紧反馈)

客户端将文本文件中的数据,复制到服务器端输出的新的java文件中,然后服务器端要给客户端反馈数据,客户端将反馈的数据展示

客户端:

	public static void main(String[] args) throws Exception {
		Socket s=new Socket("172.21.195.19", 10086);
		
		BufferedReader br=new BufferedReader(new FileReader("ServerSocketDemo.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();
		
		InputStream in = s.getInputStream();
		byte[] by=new byte[1024];
		int len = in.read(by, 0, by.length);
		System.err.println(new String (by,0,len));
		
		s.close();
		br.close();
	}
	

服务端:

	public static void main(String[] args) throws Exception {
		ServerSocket ss=new ServerSocket(10086);
		Socket s = ss.accept();
		BufferedWriter bw=new BufferedWriter(new FileWriter("Copy.java"));
		BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
		String line=null;
		while((line=br.readLine())!=null) {
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		
		
		OutputStream out = s.getOutputStream();
		byte[] by = "复制成功!!!".getBytes();
		out.write(by, 0, by.length);
		out.flush();
		
		s.close();
		bw.close();
	}

反射

什么是反射:

  反射就是通过获取class字节码文件对象/Class的类对象,获取该字节码文件对象中的成员变量,构造方法,和成员方法

 Field: 简称成员变量 (Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。

  反射的字段可能是一个类(静态)字段或实例字段。

 Constructor:简称构造方法:提供关于类的单个构造方法的信息以及对它的访问权限。

 Method:简称成员方法:类或接口上单独某个方法(以及如何访问该方法)的信息

  如何获取class字节码文件对象/Class的类对象

  三种方式来获取这个class字节码文件对象:

  1)Object中的getClass()

  2)任何数据类型的静态属性class

  3)Class类中的方法:

  forName(String className)

  forName("类路径")

开发中使用第三种方式,forName方法中的参数是一个String类型,以后可以用字符串类型数据作为配置文件!

通过字节码文件对象获取构造方法并使用.

 创建Person对象

  Person p = new Person() ;

  System.out.println(p) ;

1) 先获取Person类的字节码文件对象

2)public Constructor<?>[] getConstructors()

Class 对象所表示的类的所有公共构造方法

public Constructor<?>[] getDeclaredConstructors():获取当前字节码文件对象中的所有的构造方法

Class c=Class.forName("反射的三种实现方式.Person");
//		获取所有的共有构造函数
//		Constructor[] cons = c.getConstructors();
		
//		获取所有的构造函数
		Constructor[] cons = c.getDeclaredConstructors();
		for(Constructor c1:cons) {
			System.out.println(c1);
		}

2)获取单个构造方法(公共的,带三个参数的)

public Constructor<T> getConstructor(Class<?>... parameterTypes)

3)创建构造方法表示的该类的实例对象

Object obj = con.newInstance("高圆圆",27,"户县") ;

public void setAccessible(boolean flag)

值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查

public static void main(String[] args) throws Exception {
		Class c=Class.forName("反射的三种实现方式.Person");
//		获取公共的无惨构造函数
		Constructor cons= c.getConstructor();
		System.out.println(cons);
		System.out.println("-------------------");
//		获取指定的公共构造函数
		Constructor cc=c.getConstructor(String.class,int.class,String.class);
		System.out.println(cc);
		System.out.println("-------------------");
//		获取私有的构造函数
		Constructor c2=c.getDeclaredConstructor(String.class);
//		创建该类的对象
//		取消访问检查
		c2.setAccessible(true);
		Object obj = c2.newInstance("gao");
		System.out.println(c2);
		System.out.println(obj);
		System.out.println("-------------------");
	}	
	

获取当前字节码文件对象中的所有的公共的成员变量

public Field[] getDeclaredFields():获取当前字节码文件对象中所有的字段

public Field[] getFields()

public void set(Object obj,Object value)

参数1:表示给哪个对象设置当前字段的值

参数2:表示给当前获取的哪个Field对象的字段设置一个新的值

Class c=Class.forName("反射的三种实现方式.Person");
//		获取所有共有的字段
		Field[] f1 = c.getFields();
		for(Field f:f1) {
			System.out.println(f);
		}
		
		System.out.println("---------------");	
//		获取所有的字段
		Field[] f2 = c.getDeclaredFields();
		for(Field ff:f2) {
			System.out.println(ff);
			
		}
		System.out.println("----------------");
//		给共有的字段赋值
		Constructor con=c.getConstructor();
		Object obj = con.newInstance();
		Field f3 = c.getField("address");
		f3.set(obj, "北京");
		System.out.println(obj);
		System.out.println(f3);
		System.out.println("-----------------");
//		给私有的字段赋值
		Field f4 = c.getDeclaredField("name");
		f4.setAccessible(true);
		f4.set(obj, "高圆圆");
		System.out.println(obj);
		System.out.println(f4);
		System.out.println("-----------------");
		}

获取当前字节码文件对象中的所有的公共的成员方法(包括父类中的)

public Method[] getMethods()

public Method[] getDeclaredMethods():所有的成员方法 

获取单个的成员方法,Method  

public Method getMethod(String name, Class<?>... parameterTypes)

参数1: 表示方法名

参数2:表示当前方法的参数数据类型的静态class属性

public Object invoke(Object obj, Object... args)

参数1:指定的哪个对象上调用底层invoke(),

参数2:表示的调用那个方法所传递的实际参数

public static void main(String[] args) throws Exception {
		Class c=Class.forName("反射的三种实现方式.Person");
//		获取所有方法
		Method[] m1 = c.getDeclaredMethods();
		for (Method m : m1) {
			System.out.println(m);
			
		}
		System.out.println("-----------------");
//		创建对象
		Constructor con=c.getConstructor();
		Object obj = con.newInstance();
//		调用共有无参方法
		Method m2 = c.getMethod("show");
		m2.invoke(obj);
		System.out.println("-----------------");
//		调用共有有参
		Method m3=c.getMethod("getString", String.class,int.class);
		System.out.println(m3.invoke(obj,"高圆圆",100));
		System.out.println("-----------------");
//		调用私有无参
		Method m4=c.getDeclaredMethod("function");
		m4.setAccessible(true);
		m4.invoke(obj);
	}

代理: 在程序的执行过程中,通过一个类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<?>[]

  getInterfaces()

public class MyInvacationHandler implements InvocationHandler {

	//给哪个对象生成代理  (目标对象)
	private Object target ;
	public MyInvacationHandler(Object target) {
		this.target = target ;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		//实现代理的程序
		System.out.println("权限校验");
		Object obj = method.invoke(target, args) ;
		System.out.println("日志记录");
		return obj;//返回的就是代理对象
	}

}
public static void main(String[] args) {

		// 创建UserDao对象
		UserDao ud = new UserDaoImpl();
		ud.add();
		ud.delete();
		ud.update();
		ud.find();

		System.out.println("------------------");

		// 针对UserDao对象ud给它生产一个代理对象
		// 调用处理程序,接口实现类中产生代理
		MyInvacationHandler handler = new MyInvacationHandler(ud);

		UserDao ud2 = (UserDao) Proxy.newProxyInstance(ud.getClass().getClassLoader(), ud.getClass().getInterfaces(),
				handler);
		ud2.add();
		ud2.delete();
		ud2.update();
		ud2.find();
	}

猜你喜欢

转载自blog.csdn.net/m0_37167369/article/details/80592156
今日推荐