javase-day12

aReflection_01GetAllConstructorDemo

package com.se.aReflection;

import com.se.util.ReflectionUtil;

import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;

/**
 * 获取所有构造器,包括私有的
 *
 * 修饰词对应的是常量,public-->1  private-->2 protected-->4 default-->0
 *                  static-->8  final-->16  synchronized-->32
 */

public class _01GetAllConstructorDemo {
    public static void main(String[] args) {
        try {
            //先获取描述类的对象,描述Person类型
            Class<?> aClass = Class.forName(ReflectionUtil.getClassNameString());
            //获取所有的构造器
            Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
            //遍历数组
            for (Constructor<?> constructor : declaredConstructors) {
                //获取构造器的修饰词
                System.out.println("构造器的修饰词:" + constructor.getModifiers());
                //获取构造器的名字
                System.out.println("构造器的名字:" + constructor.getName());
                //获取构造器的参数
                Parameter[] parameters = constructor.getParameters();
                for (Parameter parameter : parameters) {
                    //获取参数的类型
                    System.out.println("参数类型:" + parameter.getType());
                    //获取参数的名字
                    System.out.println("参数名字:" + parameter.getName());
                }
                System.out.println("-------------------");
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

aReflection_02GetAllMethodDemo

package com.se.aReflection;

import com.se.util.ReflectionUtil;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * 获取一个类中所有的方法,包括私有的
 */

public class _02GetAllMethodDemo {
    public static void main(String[] args) {
        try {
            //获取描述Person类的类对象
            Class<?> aClass = Class.forName(ReflectionUtil.getClassNameString());
            //获取类中所有的方法
            Method[] methods = aClass.getDeclaredMethods();
            //遍历
            for (Method mothod : methods) {
                //获取方法修饰词
                System.out.println("修饰词" + mothod.getModifiers());
                //方法的返回值类型
                System.out.println("返回值类型" + mothod.getReturnType());
                //方法名
                System.out.println("方法名" + mothod.getName());
                //方法参数
                Parameter[] parameters = mothod.getParameters();
                for (Parameter parameter : parameters) {
                    //参数类型
                    System.out.println("参数类型" + parameter.getType());
                }
                System.out.println("-------------------");
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

bMember_01GetFieldDemo

package com.se.bMember;

import com.se.util.ReflectionUtil;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 获取成员变量
 */

public class _01GetFieldDemo {
    public static void main(String[] args) {
        try {
            //获取描述类对象
            Class<?> aClass = Class.forName(ReflectionUtil.getClassNameString());
            //获取所有的属性
            Field[] declaredFields = aClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                //获取属性修饰词
                System.out.println("修饰词" + declaredField.getModifiers());
                //属性的类型
                System.out.println("属性类型" + declaredField.getType());
                //属性名
                System.out.println("属性名" + declaredField.getName());
            }
            //假如不知道有哪些方法。可以指定一个方法名,查看是否返回
            //注意,如果获取不到方法,抛异常,NoSuchMethodException
            Method sleep = aClass.getMethod("setName", String.class);

            //假如不知道有那些属性,可以指定一个属性,查看是否返回正确
            //注意,如果获取不到属性,抛异常,NoSuchFieldException
            Field gender = aClass.getField("gender");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

cInstance_01PersonDemo

package com.se.cInstance;

import com.se.util.ReflectionUtil;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 使用反射机制实例化一个对象
 */

public class _01PersonDemo {
    public static void main(String[] args) {
        try {
            //获取Person的描述类对象
            Class<?> aClass = Class.forName(ReflectionUtil.getClassNameString());
            //调用无参构造器,实例化对象
            Object o = aClass.newInstance();
            //实例化之后,属性都是默认值,需要进行初始化,覆盖默认值
            Field name = aClass.getDeclaredField("name");
            name.setAccessible(true);
            //将属性与对象关联上,并赋值
            name.set(o, "小蕊");

            Field age = aClass.getDeclaredField("age");
            age.setAccessible(true);
            age.set(o, 22);

            Field gender = aClass.getDeclaredField("gender");
            gender.setAccessible(true);
            gender.set(o, '女');

            System.out.println(o);

            //调用setGender方法,将'女'覆盖
            Method setGender = aClass.getMethod("setGender", char.class);
            //方法与对象关联,使用invoke方法
            setGender.invoke(o, '男');

            System.out.println(o);


            //调用sleep方法
            Method sleep = aClass.getDeclaredMethod("sleep", String.class);
            sleep.setAccessible(true);
            sleep.invoke(o, "床");


        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
}

dNetApi_01InetAddressDemo

package com.se.dNetApi;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

/**
 * 常用API之InetAddress
 *  1. 该类用于描述一台机器的Ip和主机信息
 *  2. 常用方法:
 *     - static InetAddress getLocalHost()
 *     - static InetAddress getByName(String host)
 *     - String getHostAddress()
 *     - String getHostName()
 */


public class _01InetAddressDemo {
    public static void main(String[] args) {
        try {
            //获取一个描述本机信息的InetAddress对象  主机名称和ip地址
            InetAddress addr = InetAddress.getLocalHost();
            System.out.println(addr);
            //获取里面的主机名称
            System.out.println("主机名称:"+addr.getHostName());
            //获取里面的ip地址  192.168.1.121
            System.out.println("ip地址:"+addr.getHostAddress());
            //Ip的字节序列形式  [-64, -88, 1, 121]
            System.out.println("Ip的字节序列形式:"+ Arrays.toString(addr.getAddress()));


            //描述本机的形式有:127.0.0.1   localhost  具体IP
           InetAddress  inet1= InetAddress.getByName("192.168.1.121");
           System.out.println(inet1);

           //获取其他域名或者指定IP信息
            InetAddress inet2 = InetAddress.getByName("www.baidu.com");
            System.out.println(inet2.getHostAddress());
            System.out.println(inet2.getHostName());

            //获取域名对应的所有的主机
            InetAddress[] allByName = InetAddress.getAllByName("www.baidu.com");
            System.out.println(allByName.length);
            for (InetAddress inetAddress : allByName) {
                System.out.println(inetAddress.getHostAddress());
            }
        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        }

    }
}

dNetApi_02ServerSocketDemo

package com.se.dNetApi;

import com.sun.xml.internal.ws.addressing.WsaActionUtil;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * TCP通信协议的服务端API
 *   1. ServerSocket 用来描述TCP的服务端
 *   2. 常用构造器:
 *       ServerSocket(int port): 用于指定一个端口号,返回具体的实例
 *   3. 常用方法:
 *       - setSoTimeout(int timeout): 用于定义一个阻塞的超时时间,单位毫秒,超时报异常,
 *                            设置为0时候表示不超时,一直等待,默认为0
 *       - accept(): 阻塞方法,监听客户端的连接请求,监听到则返回一个Socket对象,表示客户端的连接
 */

public class _02ServerSocketDemo {
    public static void main(String[] args) {
        //创建一个服务端的实例对象,指定端口号,必须是没使用过的
        try {
            ServerSocket server = new ServerSocket(9999);
            //设置超时时间,单位毫秒
//            server.setSoTimeout(10000);
            System.out.println("等待客户端连接,仅限10s");
            //调用accpet方法,监听客户端连接,是否连接服务器
            Socket socket =server.accept();//如果指定了超时时间,改时间没客户端连接,跑SocketException异常
            System.out.println("客户端连接成功");

            //获取输入流,等待客户端传入信息
            InputStream inputStream = socket.getInputStream();
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(inputStream, "utf-8"));
            String info = br.readLine();
            System.out.println("客户端发送的信息:"+info);

//            System.out.println("服务端ip:"+server.getInetAddress().getHostAddress());
//            System.out.println("服务端ip:"+server.getInetAddress().getHostName());
//            System.out.println("详细内容:"+server.getLocalSocketAddress());
//            System.out.println("正在使用的端口号:"+server.getLocalPort());
//            System.out.println("服务端是否关闭:"+server.isClosed());
//            System.out.println("超时时间:"+server.getSoTimeout());
//            System.out.println("服务器绑定的端口号是否正确:"+server.isBound());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

dNetApi_03SocketDemo

package com.se.dNetApi;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;

/**
 * TCP通信协议额客户端API
 *  1. Socket这个类用于描述TCP的客户端
 *  2. 常用构造器:
 *       Socket(String hostname,int port): 指定想要的服务器的IP和端口号
 *       Socket(InetAddress address,int port): 指定服务器的地址和端口号
 */

public class _03SocketDemo {
    public static void main(String[] args) {
        //指定服务器的IP和端口号,返回一个客户的Socket对象,连接服务器
        try {
//            Socket socket = new Socket("127.0.0.1", 9999);
            Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9999);


            OutputStream out = socket.getOutputStream();
            PrintWriter pw = new PrintWriter(
                    new OutputStreamWriter(out, "utf-8"), true);
            pw.println("你好");

            //测试客户端的其他方法
            InetAddress inerAddress = socket.getInetAddress();
            System.out.println("远程服务端的地址信息:" + inerAddress);
            InetAddress localAddress = socket.getLocalAddress();
            System.out.println("客户端的地址信息:" + localAddress);
            int localPort = socket.getLocalPort();
            System.out.println("客户端自己分配用于通信的端口号:" + localPort);


        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

util_RefilectionUtil

package com.se.util;

import java.io.FileReader;
import java.util.Properties;

/**
 * 反射工具类
 */
public class ReflectionUtil {
    public static String getClassNameString() {
        String classname = null;
        try (FileReader fr = new FileReader("./reflection.properties")) {
            //创建一个Propeties配置文件对象
            Properties prop = new Properties();
            //调用方法读取流里的信息,就会自动将配置文件里的key=value对封装到自身
            prop.load(fr);
            //解析prop,通过key获取value
            classname = prop.getProperty("classname");

        } catch (Exception e) {
            e.printStackTrace();
        }
        return classname;
    }

    public static void main(String[] args) {
        System.out.println(ReflectionUtil.getClassNameString());
    }
}

VO_Person

package com.se.VO;

public class Person {
    private String name;
    private int age;
    private char gender;

    public Person(){}
    private Person(String name){
        this.name = name;
    }
    public Person(String name,int age,char gender){
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                '}';
    }

    public char getGender() {
        return gender;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }

    private void sleep(String obj){
        System.out.println(name+"喜欢躺在"+obj+"睡觉");
    }





}

refiection.properties

classname=com.se.VO.Person

chat_ChatClient

package com.se.chat;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

/**
 * 聊天客户端
 */

public class ChatClient {
    //定义一个TCP通信协议的客户端属性
    private Socket socket;

    public ChatClient() {
        //获取Socket对象,同时向服务器端发起连接请求,连接失败:ConnectException
        try {
            socket = new Socket("localhost", 8888);
        } catch (IOException e) {
            System.out.println("服务器崩溃");
        }
    }

    //聊天的主方法
    private void start() {
        //获取向服务器发送信息的输入流对象
        try {
            //获取一个服务端信息的处理器任务
            Runnable task = new GetServerInfoHandler();
            Thread thread = new Thread(task);
            thread.start();

            //获取向服务器发送信息的输出流对象
            OutputStream outputStream = socket.getOutputStream();
            //封装成字节缓存流,可以按行输出
            PrintWriter out = new PrintWriter(
                    new OutputStreamWriter(
                            outputStream, "utf-8"), true);

            //使用控制台扫描对象类型,不断扫描控制台上的文字
            Scanner scan = new Scanner(System.in);
            //设置昵称
            System.out.println("请输入你的昵称");
            String nickname = scan.nextLine();
            //将昵称发送到服务端,服务器校验昵称是否可用
            out.println(nickname);

            System.out.println("开始聊天");
            while (true) {
                String info = scan.nextLine();
                //将扫描的信息发送服务端
                out.println(info);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        //创建具体的聊天对象
        ChatClient client = new ChatClient();
        //调用客户端的主方法
        client.start();
    }

    class GetServerInfoHandler implements Runnable {
        public void run() {
            try {
                //获取向服务器发送信息的输入流对象
                InputStream inputStream = socket.getInputStream();
                BufferedReader br = new BufferedReader(
                        new InputStreamReader(inputStream, "utf-8"));

                //获取自己的昵称
                String nickname = br.readLine();
                System.out.println("你的昵称为:" + nickname);

                String line = "";
                while ((line = br.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

chat_ChatServer

package com.se.chat;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 聊天服务器
 */

public class ChatServer {
    //定义一次TCP通信协议的服务端属性
    private ServerSocket server;
    //添加一个Map属性,存储多个客户端的标识与输出流对象  Map集合(散列表)
    private Map<String, PrintWriter> allOut;

    public ChatServer(int port) {
        try {
            server = new ServerSocket(port);
            //给Map集合赋值
            allOut = new HashMap<String, PrintWriter>();
        } catch (IOException e) {
            System.out.println("服务器启动失败");
        }
    }

    //聊天的主方法
    private void start() {
        try {
            while (true) {
                System.out.println("等待服务器连接");
                Socket socket = server.accept();
                System.out.println("一个客户端连接");

                //每连接一个客户端的Socket对象,将其放入并发线程
                Runnable task = new GetClientInfoHandler(socket);
                Thread thread = new Thread(task);
                thread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        //创建一个具体的服务器对象
        ChatServer chatServer = new ChatServer(8888);
        //调用聊天的主方法
        chatServer.start();
    }

    //定义一个处理客户端信息的线程
    class GetClientInfoHandler implements Runnable {
        //因为run方法使用了socket对象,所以需要将socket对象作为参数
        //所有在该类中添加属性,run方法可以访问属性
        private Socket socket;

        //提供一个构造器,将start方法中的局部变量socket传进来,给属性赋值, 这样,run方法中使用的socket就是
        //start方法中的局部变量指向的对象
        public GetClientInfoHandler(Socket socket) {
            this.socket = socket;
        }

        public void run() {
            String nickname = null;
            try {
                //通过服务端的Socket对象,获取输入流,接收客户端发送信息
                InputStream inputStream = socket.getInputStream();
                BufferedReader br = new BufferedReader(
                        new InputStreamReader(inputStream, "utf-8"));

                //通过服务端的Socket对象,获取输出流,将信息返回给客户端
                OutputStream outputStream = socket.getOutputStream();
                PrintWriter pw = new PrintWriter(
                        new OutputStreamWriter(outputStream, "utf-8"), true);

                //先获取客户端的昵称
                nickname = br.readLine();
                //循环判断昵称是否重复
                while (allOut.containsKey(nickname)) {
                    nickname = nickname + Math.random();
                }
                //将昵称返回给客户端
                pw.println(nickname);

                //将昵称与输出流对象存入Map集合
                allOut.put(nickname, pw);
                System.out.println("在线人数" + allOut.size());

                //循环打印客户端发来的信息
                String info = "";
                while ((info = br.readLine()) != null) {
                    //将信息info发送给所有客户端
                    sendToAllClient(nickname, info);
                }
            } catch (IOException e) {
                System.out.println("一个客户端退出");
                //删除相应的键值对
                allOut.remove(nickname);
                System.out.println("在线人数" + allOut.size());

            }
        }
    }

    public void sendToAllClient(String nickname, String info) {
        //遍历Map里的所有输出流,来发送info信息
        Set<String> nicks = allOut.keySet();
        for (String nick : nicks) {
            //获取输出流,然后发送信息
            PrintWriter writer = allOut.get(nick);
            writer.println(nickname + "说:" + info);
        }
    }
}

chat1_ChatClient

package com.se.chat1;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.net.Socket;
import java.util.Map;

public class ChatClient extends JPanel {

    /* 定义Sockt属性 */
    private Socket socket;

    private JTextArea welcomeArea;
    /* 添加面板属性,三个文本框属性 */
    private JTextArea showText;
    private JTextArea countText;
    private JTextArea nameText;

    private JTextArea oneText;
    private JTextArea inputText;

    private JTextArea noticeText;

    private JButton sendButton;
    private JButton closeButton;
    public ChatClient() {
        try {
            // 取消面板的默认布局, 使用绝对布局,即使用坐标方式进行布局
            this.setLayout(null);
            // 修改面板的背景颜色
            this.setBackground(new Color(200, 200, 200));
            //调用自己封装的初始化布局方式
            initLayout();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化自己的页面布局:
     * 1. 头部布局
     * 2. 上半部身体的布局
     * 3. 下半部身体的布局
     * 4. 聊天输入框的布局
     * 5. 两个按钮的布局
     */
    public void initLayout(){
        headLayout();
        body1Layout();
        body2Layout();
        chatInputArea();
        buttonArea();
    }

    /**
     * 两个按钮的布局
     */
    private void buttonArea() {
        //两个按钮
        firstButton();
        lastButton();
    }

    /**
     * 第二个按钮"关闭"的布局
     */
    private void lastButton() {
        closeButton = new JButton("关闭");
        closeButton.setBounds(590,550,65,35);
        this.add(closeButton);
        closeButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                int option = JOptionPane.showConfirmDialog(null, "您确定要离开吗");
                if (option == JOptionPane.YES_OPTION) {
                    System.exit(0);
                }
            }
        });
    }

    /**
     * 第一个按钮“发送”的布局
     */
    private void firstButton() {
        sendButton = new JButton("发送");
        sendButton.setBounds(590,505,65,35);
        this.add(sendButton);
    }

    /**
     * 聊天窗口的布局
     */
    private void chatInputArea() {
        //5. 输入窗口
        inputText = new JTextArea("输入框");
        inputText.setBackground(new Color(238,238,238));
        inputText.setBounds(5,495,580,100);
        this.add(inputText);
    }

    /**
     * 私聊的内容显示窗口,与群公告窗口的布局
     */
    private void body2Layout() {
        //5. 私聊显示窗口
        oneText = new JTextArea("私聊显示窗口");
        oneText.setBackground(new Color(238,238,238));
        oneText.setBounds(5,390,650,100);
        this.add(oneText);

        //6. 公告窗口
        noticeText = new JTextArea("公告");
        noticeText.setBackground(new Color(238,238,238));
        noticeText.setBounds(660,390,235,205);
        this.add(noticeText);
    }

    /**
     * 公共聊天显示窗口和在线成员列表窗口的布局
     */
    private void body1Layout() {
        //3. 公共聊天组件
        showText = new JTextArea("公共聊天显示窗口");
        showText.setBackground(new Color(238,238,238));
        showText.setEditable(false);// 设置不可编辑
        showText.setBounds(5,30,650,355);
        //为showText设置滚动条
        JScrollPane scroll = new JScrollPane(showText);
        //设置垂直滚动
        scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        this.add(scroll);
        this.add(showText);

        //4. 成员列表组件
        nameText = new JTextArea("成员列表");
        nameText.setBounds(660,30,235,355);
        nameText.setBackground(new Color(238,238,238));
        JScrollPane scroll1 = new JScrollPane(nameText);
        scroll1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        this.add(scroll1);
        this.add(nameText);
    }

    /**
     * 欢迎语,与 人数在线统计的 布局
     */
    private void headLayout() {
        //0. 欢迎logo
        welcomeArea = new JTextArea("欢迎进入聊天室,您的昵称是:");
        welcomeArea.setBackground(new Color(200, 200, 200));
        welcomeArea.setEditable(false);
        welcomeArea.setBounds(5,5,650,20);
        this.add(welcomeArea);

        //1. 统计人数组件
        countText = new JTextArea("在线人数:");
        countText.setBackground(new Color(200,200,200));
        countText.setBounds(660,5,235,20);
        this.add(countText);
    }

    public void start(){
    }
    public static void main(String[] args) {
        //启动聊天窗口
        JFrame frame = new JFrame("聊天室");
        frame.setUndecorated(true);
        frame.setSize(900,600);
        //创建一个面板
        ChatClient panel = new ChatClient();
        frame.setContentPane(panel);
        frame.setLocationRelativeTo(null);
//        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        //启动聊天
        panel.start();

    }
}

chat1_ChatServer

package com.se.chat1;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 聊天服务器
 */
public class ChatServer {
    //定义一个TCP通信协议的服务端属性
    private ServerSocket server;
    //添加一个Map属性,用于存储多个客户端的标识与输出流对象。 Map集合(散列表)
    private Map<String,PrintWriter> allOut;

    public ChatServer(int port) {
        try {
            server = new ServerSocket(port);
            //给map集合赋值
            allOut = new HashMap<String,PrintWriter>();

        } catch (IOException e) {
            System.out.println("---服务器启动失败---");
        }
    }

    /**
     * 聊天的主方法
     */
    public void start() {
        try {
            while (true) {
                System.out.println("---等待客户端连接---");
                Socket socket = server.accept();
                System.out.println("---一个客户端连接上了---");

                //每获取一个客户端的Socket对象,就应该将其放入一个并发线程中
                Runnable task = new GetClientInfoHandler(socket);
                Thread thread = new Thread(task);
                thread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        //创建一个具体的服务器对象
        ChatServer chatServer  = new ChatServer(8888);
        //调用聊天的主方法
        chatServer.start();

    }

    /**
     * 定义一个处理客户端信息的处理器,即一个任务体
     */
    class GetClientInfoHandler implements Runnable {
        //因为run方法中使用了 start方法中的socket局部变量
        //所以可以在该类中添加一个属性,run方法中可以访问该类的属性
        private Socket socket;
        //提供一个构造器,将start方法中的局部变量socket传进来,给属性赋值, 这样,run方法中使用的socket就是
        //start方法中的局部变量指向的对象
        public GetClientInfoHandler(Socket socket) {
            this.socket = socket;
        }
        @Override
        public void run() {
            String nickname = null;
            try {
                //通过服务端的Socket对象,获取输入流,接受客户端发送过来的数据
                InputStream inputStream = socket.getInputStream();
                BufferedReader br = new BufferedReader(
                        new InputStreamReader(inputStream,"utf-8"));

                //通过服务端的Socket对象,获取输出流,将信息返回给客户端
                OutputStream outputStream = socket.getOutputStream();
                PrintWriter pw = new PrintWriter(
                        new OutputStreamWriter(outputStream,"utf-8"),true);



                //先获取客户端的昵称
                nickname = br.readLine();
                //判断是否已经被占用,如果已经被占用,加后缀
                while(allOut.containsKey(nickname)){
                    nickname = nickname+Math.random();
                }
                //将昵称告诉客户端
                pw.println(nickname);

                //将输出流添加到Map集合中
                allOut.put(nickname,pw);
                System.out.println("-----在线人数:"+allOut.size()+"--------");
                //循环打印客户端发送过来的信息
                String info = "";
                while ((info = br.readLine()) != null) {
                    // 如果信息不是以@开头的,说明不是私聊,将信息info发送到所有的客户端里
                    if(!info.startsWith("@")){
                        sendToAllClient(nickname,info);
                    }else{
                        sendToOneClient(nickname,info);
                    }
                }
            } catch (IOException e) {
                System.out.println("---一个客户端离线了---");
                //删除对应的键值对
                allOut.remove(nickname);
                System.out.println("-----在线人数:"+allOut.size()+"--------");
            }
        }
    }
    public void sendToOneClient(String nickname, String info) {
        //获取要私聊的对象名称
        //获取第一个冒号的下标
        int index = info.indexOf(":");
        String toNickName = info.substring(1, index);
        //找到对应的流对象
        PrintWriter printWriter = allOut.get(toNickName);
        printWriter.println(nickname+"对你说:"+info.substring(index+1));
    }
    public void sendToAllClient(String nickname, String info) {
        //遍历Map里的所有输出流,来发送info信息
        Set<String> nicks = allOut.keySet();
        for (String nick : nicks) {
            //获取对应的输出流,然后发送信息
            PrintWriter writer = allOut.get(nick);
            writer.println(nickname+"说:"+info);
        }
    }
}

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值