Java程序猿必学第二十三篇——网络编程(聊天室)与反射
2021/11/10 22:15:48
本文主要是介绍Java程序猿必学第二十三篇——网络编程(聊天室)与反射,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
//1. 网络编程案例 //1.1 注册功能 //案例:注册功能 //分析: //1.客户端与服务器建立连接 //2.客户端准备好注册数据,拼成一个字符串;例如:{id:"1001",name:"zs",age:30} //3.发送注册数据,服务器接收数据 //4.服务器拆分数据,取出id对应的value作为key,接收的注册信息作为value //5.判断key在配置文件中是否存在,如果存在,则返回"已存在" //6.不存在,把这些数据存到配置文件,并返回“注册成功” //-----服务器------ public class Server { public static void main(String[] args) throws IOException { ServerSocket ss = new ServerSocket(9527); Socket socket = ss.accept(); InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String msg = br.readLine(); //{id:1001,name:zs,age:30} String strId = msg.split(",")[0]; //{id:1001 String id = strId.split(":")[1]; //1001 //通过Properties集合去加载配置文件 Properties p = new Properties(); p.load(new FileInputStream("user.properties")); OutputStream os = socket.getOutputStream(); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os)); if(p.containsKey(id)) { bw.write("已存在"); }else { Tool.saveProperties(id,msg); //将数据存储到配置文件 bw.write("注册成功"); } bw.newLine(); bw.flush(); IOUtils.closeAll(bw,os,br,is,socket); } } //-----客户端------ public class Client { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.0.1",9527); OutputStream os = socket.getOutputStream(); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os)); String json = getData(); //{id:1001,name:zs,age:30} //发数据 bw.write(json); bw.newLine(); bw.flush(); InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String msg = br.readLine(); System.out.println("服务器响应:"+msg); IOUtils.closeAll(is,br,os,bw,socket); } private static String getData() { Scanner sc = new Scanner(System.in); System.out.println("请输入ID:"); String id = sc.next(); System.out.println("请输入用户名:"); String name = sc.next(); System.out.println("请输入年龄:"); int age = sc.nextInt(); return "{id:"+id+",name:"+name+",age:"+age+"}"; } } //----工具类---- public class Tool { public static void saveProperties(String id, String msg) throws FileNotFoundException, IOException { Properties properties = new Properties(); properties.put(id, msg); properties.store(new FileOutputStream("user.properties"), ""); } } //1.2 聊天室程序 //案例:聊天室程序 //分析: 多人聊天---多线程 //1.通过多线程形式接收多个客户端的连接 //2.客户端要录入姓名,传入服务器接收,并存储到线程中 //(注意:客户端的发送和接收要分为两个线程,才能方便群发) //3.服务器给客户端回应“欢迎进入聊天室” //4.该客户端就可以实时发数据聊天了 //5.要实现服务器群发信息给客户端,需要先将所有线程对象存储 //6.退出方式,客户端退出,其他用户应该都知道 -------服务器------- public class Server { public static List<ServerThread> list = new ArrayList<ServerThread>(); public static void main(String[] args) throws IOException { ServerSocket ss = new ServerSocket(9527); //多线程方式监听及创建socket while(true) { Socket socket = ss.accept(); System.out.println("有一个客户端进来了"); ServerThread st = new ServerThread(socket); st.start(); list.add(st); //存储线程对象 } } } //------服务器线程------- public class ServerThread extends Thread { private Socket socket; private BufferedReader br; private BufferedWriter bw; public ServerThread(Socket socket) throws IOException { this.socket = socket; br = new BufferedReader(new InputStreamReader(socket.getInputStream())); bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); } @Override public void run() { try { sendHello(); //欢迎 while(true){ String name = this.br.readLine(); //读取到数据后,发给自身 String msg = this.getName()+"说:"+name; //循环遍历线程对象,除了自己,都发一份出去 for(ServerThread st : Server.list) { if(st!=this) { st.bw.write(msg); st.bw.newLine(); st.bw.flush(); } } } } catch (Exception e) { String msg = this.getName()+"退出了聊天室"; //群发退出信息 Server.list.remove(this); //将当前线程对象在集合中移除 for(ServerThread st : Server.list) { //移除后群发 try { st.bw.write(msg); st.bw.newLine(); st.bw.flush(); } catch (IOException e1) { e1.printStackTrace(); } } }finally { IOUtils.closeAll(bw,br,socket); } } private void sendHello() throws IOException { String name = br.readLine(); //读取到数据后,发给自身 String msg = "【温馨提示】:欢迎"+name+"进入聊天室"; this.setName(name); //记录客户的访问 bw.write(msg); bw.newLine(); bw.flush(); } } //------客户端------- public class Client { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.0.1",9527); //客户端读写分离 new WriteClient(socket).start(); new ReadClient(socket).start(); } } //-------客户端写线程------- public class WriteClient extends Thread { private Socket socket; public WriteClient(Socket socket) { this.socket = socket; } @Override public void run() { OutputStream os = null; BufferedWriter bw = null; try { os = socket.getOutputStream(); bw = new BufferedWriter(new OutputStreamWriter(os)); System.out.println("请输入用户名:"); Scanner sc = new Scanner(System.in); while(true) { String name = sc.next(); //第一次是输入名字,后面就是聊天内容 bw.write(name); bw.newLine(); bw.flush(); } } catch (IOException e) { e.printStackTrace(); }finally { IOUtils.closeAll(os,bw,socket); } } } //-------客户端读线程-------- public class ReadClient extends Thread { private Socket socket; public ReadClient(Socket socket) { this.socket = socket; } @Override public void run() { InputStream is = null; BufferedReader br = null; try { is = socket.getInputStream(); br = new BufferedReader(new InputStreamReader(is)); while(true) { String msg = br.readLine(); System.out.println(msg); } } catch (IOException e) { e.printStackTrace(); }finally { IOUtils.closeAll(is,br,socket); } } } //2. 反射(重点) //2.1 反射概述 /** *概述:反射对象,就是类对象,是类加载的产物, 只要有了类对象,就可以知道类的所有信息(类名,接口,包名,属性,方法等) 获取类对象方式: 1.类名.class (常用) 2.对象.getClass() 3.Clas.forname("包名.类名") (常用) 结论:无论哪种方式获取的类对象,都是同一个 * */ class Person{ private String name; private int age; public Person() { System.out.println("调无参构造"); } public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void test() { System.out.println("test"); } } public class Test1 { public static void main(String[] args) throws ClassNotFoundException { Class class1 = Person.class; Class class2 = new Person().getClass(); Class class3 = Class.forName("com.qf.d_reflect.Person"); System.out.println(class1==class2); //true System.out.println(class1==class3); //true } } //2.2 反射常用方法 public class Test2 { public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException, NoSuchMethodException { Class clazz1 = Person.class; //获取反射对象 System.out.println(clazz1.getName()); //获取类名 System.out.println(clazz1.getPackage()); //获取包名 System.out.println(clazz1.getSuperclass()); //获取父类 System.out.println(Arrays.toString(clazz1.getInterfaces())); //获取接口 System.out.println(Arrays.toString(clazz1.getFields())); //性能高,不能处理私有权限属性 System.out.println(Arrays.toString(clazz1.getDeclaredFields())); //(常用)可以处理私有权限 System.out.println(Arrays.toString(clazz1.getMethods()));//(常用) System.out.println(Arrays.toString(clazz1.getConstructors())); //获取所有构造器 System.out.println(clazz1.getDeclaredField("name")); //(常用) 获取Field对象 System.out.println(clazz1.getMethod("test")); //(常用) 获取Method对象 System.out.println(clazz1.newInstance()); //调无参构造 (常用) } } //2.3 反射操作属性 //通过反射对象,给私有属性赋值及取值 //分析: //1.获取反射对象 //2.获取Field对象 //3.调用set方法赋值 ,通过get方法取值 class Student{ private String name; private int age; public String getName() { return name; } public void hello(String name,int age) { System.out.println("反射的方法调用--"+name+"--"+age); } } public class Test1 { public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException { Class clazz = Student.class; Field field = clazz.getDeclaredField("name"); field.setAccessible(true); //开启私有权限 Student st = (Student) clazz.newInstance(); field.set(st, "zsf"); System.out.println(field.get(st)); System.out.println(st.getName()); //验证value值是否存储到name属性 } } //2.4 反射操作方法 //案例2:通过反射对象调用方法 //1.获取反射对象 //2.通过反射获取Method对象,传方法名和反射类型 //3.通过Method对象调invoke方法 //反射作用:可以灵活动态操作属性和方法 public class Test2 { public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { Class<Student> class1 = Student.class; //获取Method对象,参数1:方法名 后面参数:参数类型反射对象 Method method = class1.getMethod("hello", String.class,int.class); method.invoke(class1.newInstance(), "谭小虎",28); } } //2.5 反射应用场景 //案例3:通过反射对象灵活的获取老师和学生的对象 class Teacher{ } public class Test3 { public static void main(String[] args) throws InstantiationException, IllegalAccessException { //常规获取对象方式: //弊端: 每次获取对象时,都创建了不同的方法 Teacher teacher = Tool.getTeacher(); Student student = Tool.getStudent(); //使用反射灵活获取对象 Teacher t1 = Tool.getObject(Teacher.class); Student s1 = Tool.getObject(Student.class); System.out.println(t1+"---"+s1); } } //----工具类调用----- public class Tool { public static Teacher getTeacher() { return new Teacher(); } public static Student getStudent() { return new Student(); } //泛型方法 public static <T> T getObject(Class<T> class1) throws InstantiationException, IllegalAccessException { return class1.newInstance(); } }
这篇关于Java程序猿必学第二十三篇——网络编程(聊天室)与反射的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-13TiDB + ES:转转业财系统亿级数据存储优化实践
- 2024-05-09“2024鸿蒙零基础快速实战-仿抖音App开发(ArkTS版)”实战课程已上线
- 2024-05-09聊聊如何通过arthas-tunnel-server来远程管理所有需要arthas监控的应用
- 2024-05-09log4j2这么配就对了
- 2024-05-09nginx修改Content-Type
- 2024-05-09Redis多数据源,看这篇就够了
- 2024-05-09Google Chrome驱动程序 124.0.6367.62(正式版本)去哪下载?
- 2024-05-09有没有大佬知道这种数据应该怎么抓取呀?
- 2024-05-09这种运行结果里的10.100000001,怎么能最快改成10.1?
- 2024-05-09企业src漏洞挖掘-有意思的命令执行