Android Day20使用Socket模拟私聊群聊功能

内容

使用Socket模拟私聊群聊功能

具体内容

1.使用接口定义聊天的规范

public interface ChatProtocol {
//登录
String LOGIN_FLAG = "u+";
//私聊
String PRIVATE_FLAG = "p+";
//群聊
String PUBLIC_FLAG = "a+";

//分隔符
String SPLIT_FLAG = "♥";

//成功的状态
String SUCCESS = "1";
String FAILURE = "-1";
}

2.创建一个类管理用户
管理所有的登录的用户Map
判断某个用户是否已经登陆

public class UserManager {
//保存所有用户信息
private Map users = new HashMap<>();

/**
 * 判断用户是否已经登录
 */
public boolean isLoogined(String name) {
    //遍历数组
    for (String key : users.keySet()) {
        if (key.equals(name)) {
            return true;
        }
    }
    return false;
}

/**
 * 保存当前登录的用户信息
 */
public void save(String name, Socket socket) {
    users.put(name, socket);
}

/**
 * 通过用户名找到对应的socket
 */
public Socket socketByName(String name) {
    return users.get(name);

}

/**
 * 通过socket对象找到对应的名称
 */
public String nameBySocket(Socket socket) {
    for (String key : users.keySet()) {
        //取出这个key对应的socket
        if (socket == users.get(key)) {
            return key;
        }
    }
    return null;
}

/**
 * 获取所有人的socket对象
 */
public Collection allUsers(){
    return users.values();
 }
}

3.服务器端和服务器端的子线程
服务器端

public class Server {
//用于保存每一个用户对应的姓名和socket
public static UserManager userManager = new UserManager();

public static void main(String[] args) {
    try (ServerSocket ss = new ServerSocket(8888)) {
        //监听所有来连接的客户端
        while (true) {
            Socket socket = ss.accept();

            //让子线程处理这个socket
            new ServerThread(socket).start();
        }
    } catch (IOException e) {

     } 
   }
}

服务器端的子线程 继承于Thread

class ServerThread extends Thread {
private Socket socket;

public ServerThread(Socket socket) {
    this.socket = socket;
}

@Override
public void run() {


    try {
        BufferedReader br;
        PrintStream ps;
        //登录
        //1.得到对应的输入流对象
        br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //得到对应的输出流
        ps = new PrintStream(socket.getOutputStream());
        String line;
        while ((line = br.readLine()) != null) {
            //登录 u+  u+
            if (line.startsWith(ChatProtocol.LOGIN_FLAG) && line.endsWith(ChatProtocol.LOGIN_FLAG)) {
                String[] items = line.substring(2).split("u+");
                String name = items[0];

                //获取名字
                String neme = line.substring(2, line.length() - 2);//不包含这一个所以要取到下一个

                //判断这个用户是否已经登录
                if (Server.userManager.isLoogined(name)) {
                    //登录过了
                    ps.println((ChatProtocol.FAILURE));
                } else {
                    //没有登录
                    //保存当前登录的用户信息
                    ps.println(ChatProtocol.SUCCESS);
                }
            }
            //判断是不是私聊
            else if (line.startsWith(ChatProtocol.PRIVATE_FLAG) && line.endsWith(ChatProtocol.PRIVATE_FLAG)) {
                //p+jack♥hellop+
                //获取信息
                String msg = line.substring(2, line.length() - 2);
                //分割 jack hello
                String[] items = msg.split(ChatProtocol.SPLIT_FLAG);
                //用户名
                String name = items[0];
                //聊天内容
                String message = items[1];
                //通过用户名找到对应的socket
                Socket desSocket = Server.userManager.socketByName(name);
                PrintStream desPs = new PrintStream(desSocket.getOutputStream());

                //获取当前用户的名称
                String currentName = Server.userManager.nameBySocket(socket);

                //发送私聊消息
                desPs.println(currentName + "向你发来私聊" + message);
            } else {

                String m = line.substring(2, line.length() - 2);
                String curerntName = Server.userManager.nameBySocket(socket);
                //遍历所有的用户信息
                Collection sockets = Server.userManager.allUsers();
                ;
                for (Socket s : sockets) {
                    PrintStream tempps = new PrintStream(s.getOutputStream());
                    tempps.println(curerntName+"发来群聊:"+m);
                }
            }

        }
    } catch (IOException e) {
        e.printStackTrace();
     }
  }
}

4.客户端和客户端子线程
客户端

public class Client {
public static void main(String[] args) {
    //连接服务器
    BufferedReader br = null;
    PrintStream ps = null;
    BufferedReader brServer = null;

    try (Socket socket = new Socket("127.0.0.1", 8888)) {
        //登录
        //发给服务器端的输出流
        ps = new PrintStream(socket.getOutputStream());
        //接收终端输入流
        br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //接收服务器端的输入流
        brServer = new BufferedReader(new InputStreamReader(System.in));


        while (true) {
            //接收终端输入信息
            String name = JOptionPane.showInputDialog("请输入用户名");
            //拼接登陆格式
            String loginStr = ChatProtocol.LOGIN_FLAG + name + ChatProtocol.LOGIN_FLAG;
            //发送给服务器端
            ps.println(loginStr);
            //接收服务器端返回的结果

            //判断登录结果
            if (br.readLine().equals(ChatProtocol.SUCCESS)) {
                System.out.println("登录成功");
                break;
            } else {
                System.out.println("用户名已存在 请重新登录");
            }
        }
        //登录成功
        //开启线程处理服务器端的输入
        new ClientThread(socket).start();

        //接收终端输入 发送给服务器端
        String line;

        while ((line = br.readLine()) != null) {
            //发送给服务器
            ps.println(line);
        }
    } catch (IOException e) {

     }
   }
 }

客户端子线程

class ClientThread extends Thread {
private Socket socket;

public ClientThread(Socket socket) {
    this.socket = socket;
}

@Override
public void run() {
    BufferedReader br = null;
    try {
        br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
    } catch (IOException e) {
        System.out.println("网络出错");
    } finally {
        try {
            if (br != null) {
                br.close();
            }

            if (socket != null) {
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
         }
       }
    }
 }

5.聊天实现的效果


效果

你可能感兴趣的:(Android Day20使用Socket模拟私聊群聊功能)