Java面试知识点(七十一)Socket编程进阶——简易聊天室

之前介绍了 socket基础编程Java面试知识点(七十)Socket编程——C/S架构基础入门 ,包括单客户端和多客户端的情况,现在在说一下其他情况

简易聊天室

跟之前的多客户端的情况一样,也是需要多线程来保持多个连接,但是额外要引入一个线程池,需要服务器记录所有的连接客户端,这样一个客户端发送信息之后,就可以把这个信息发送给其他保持连接的客户端,代码如下:

【子线程服务类】

package test.socket.chatroom;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;

/**
 * 单一服务器线程类
 * 可以实现跟与当前线程服务器的连接的客户端的信息通讯
 * 同时还保存着当前服务器的全部连接的线程,以便实现发送给其他客户端信息
 * */
public class SingleServer implements Runnable {
    // 创建线程连接池,存储线程名和线程
    private Map<String,Socket> pool;
    // 创建socket
    private Socket socket;
    private String name;

    public SingleServer(Map<String,Socket> pool, String name,Socket socket) {
        this.pool = pool;
        this.socket = socket;
        this.name = name;
        // 将socket线程加入线程池中
        this.pool.put(this.name,this.socket);
    }

    @Override
    public void run() {
        read();
    }

    // 获取当前线程的客户端的信息
    private void read() {
        try {
            boolean flag = true;
            while (flag) {
                BufferedReader reader =
                        new BufferedReader(new InputStreamReader(socket.getInputStream()));
                if (reader.ready()) {
                    String str = reader.readLine();
                    // 服务器获得之后可以保存在本地当做日志,这里简单打印
                    System.out.println(name+"客户端: "+str);
                    // 把接收到的信息发送给其他客户端并打印
                    Iterator it = pool.keySet().iterator();
                    while (it.hasNext()) {
                        String key = (String)it.next();
                        if (this.socket != pool.get(key)) {
                            write(pool.get(key),name+"客户端: "+str);
                        }
                    }

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

    /**
     * 把信息发送到客户端
     * */
    private void write(Socket socket, String str) {
        try {
            PrintWriter writer
                    = new PrintWriter(socket.getOutputStream(),true);
            writer.println(str);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

【服务器类】

package test.socket.chatroom;

import test.test.thread1;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class Server {
    public static void main(String[] args) {
        try {
            // 监听端口
            ServerSocket server = new ServerSocket(9999);
            // 线程池
            Map<String, Socket> pool = new HashMap<>();

            System.out.println("服务器启动...");

            int i = 0;
            // 循环侦听
            while (true) {
                // 客户端id
                i++;
                String id = i+ "";
                // 开启线程
                SingleServer singleServer = new SingleServer(pool,id,server.accept());
                Thread thread = new Thread(singleServer);
                thread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

【客户端类】

package test.socket.chatroom;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class Client {
    public static void main(String[] args) {
        // 建立连接
        try {
            Socket socket = new Socket("localhost",9999);
            System.out.println("客户端启动");
            while (true) {
                // 读取信息
                BufferedReader reader
                        = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                if (reader.ready()) {
                    String str = reader.readLine();
                    System.out.println(str);
                }

                // 写信息
                PrintWriter writer =
                        new PrintWriter(socket.getOutputStream(),true);
                BufferedReader key =
                        new BufferedReader(new InputStreamReader(System.in));
                if (key.ready()) {
                    String str = key.readLine();
                    writer.println(str);
                }

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

【运行结果】
Java面试知识点(七十一)Socket编程进阶——简易聊天室_第1张图片Java面试知识点(七十一)Socket编程进阶——简易聊天室_第2张图片Java面试知识点(七十一)Socket编程进阶——简易聊天室_第3张图片Java面试知识点(七十一)Socket编程进阶——简易聊天室_第4张图片
后期还可以加上发送时间,左右分区,加上身份验证等等


还有一些问题,服务器无法发送给全部客户端信息
待续…

你可能感兴趣的:(Java面试知识汇总,java,面试)