Java Socket simplemente se da cuenta de la comunicación entre el cliente y el servidor (imitando la sala de chat)

El protocolo Java Socket TCP simplemente realiza la comunicación entre el cliente y el servidor

Efecto de ejecución:

  1. Inicie el servidor y 3 clientes
    Terminal de servicio
    Inserte la descripción de la imagen aquí
  2. Chat grupal y chat privado
    Cliente 1

Cliente 2

Proceso de implementación:

  • Servidor :
    primero cree un objeto ServerSocket de socket de servidor y vincule el puerto (inicie el servidor), luego ServerSocket llama al método accept para bloquear la espera de recibir la solicitud de un cliente, y cada vez que se recibe una solicitud, devuelve un objeto Socket del cliente (con Socket El objeto puede obtener los flujos de entrada y salida del cliente y luego realizar la transmisión de mensajes) e iniciar un nuevo hilo para procesar los mensajes del cliente, como mensajes en línea del cliente, mensajes fuera de línea del cliente, mensajes grupales, mensajes de chat privados y luego realizar el procesamiento correspondiente. .

Nota: El objeto Socket obtiene los flujos de entrada y salida del cliente también está bloqueando, por ejemplo, el método readline lee "\ n" antes de que se considere el final de la lectura, de lo contrario el programa se ha bloqueado allí, pero el método read no sabe cuándo termina la lectura porque No sabe cuándo el remitente termina de enviar el mensaje, a menos que el remitente cierre el flujo de salida y luego lea -1, terminará de leer, pero después de que el remitente cierre el flujo de salida, ya no podrá enviar mensajes al receptor. No hay Involucrado, pero cuando el receptor termina de leer el mensaje es una cuestión que vale la pena considerar.

  • Cliente :
    primero cree un objeto de socket de cliente basado en la dirección y el puerto del servidor. Con el objeto de Socket anterior, puede obtener los flujos de entrada y salida al servidor y leer y escribir mensajes, y luego crear un hilo para monitorear y procesar los mensajes del servidor. Obtenga la entrada del usuario y envíelo al servidor (ingresar mensaje de salida aquí significa salir del servidor, ingresar @xxx: mensaje de formato de mensaje significa chat privado para enviar un mensaje al cliente xxx, otros mensajes se unifican como mensajes de chat grupal, y el servidor los reenviará directamente a otros después de recibir Todos los clientes)

Código del servidor

public class Server {
    
    
    private int port = 5210;
    private ServerSocket server_socket;
    private Map<String,Socket> clients;   //存放所有访问服务器的客户端和其用户名

    public Server() throws Exception {
    
    
        //1-初始化
        server_socket = new ServerSocket(this.port);   //创建服务器
        clients = new HashMap<>();

        //2-每次接收一个客户端请求连接时都启用一个线程处理
        while(true) {
    
    
            //accept方法一直阻塞直到接收到一个客户端的请求 并返回该客户端的套接字socket
            Socket client_socket = server_socket.accept();
    		//开启新线程处理客户端的请求
            new HandleClientThread(client_socket).start();
        }
    }

    /** ----------------------------------------------------------------------------------------------------
     *      启用一个线程处理一个客户端的请求
     */
    private class HandleClientThread extends Thread{
    
    
        private Socket client_socket;    //
        private BufferedReader server_in;
        private PrintWriter server_out;
        private String client_Name;

        public HandleClientThread(Socket client_socket) {
    
    
            try {
    
    
                //初始化
                this.client_socket = client_socket;
                server_in = new BufferedReader(new InputStreamReader(this.client_socket.getInputStream()));
                server_out = new PrintWriter(this.client_socket.getOutputStream(),true);
                
                //通知刚连上的客户端输入用户名
                server_out.println("您已成功连接上聊天服务器!请输入你的用户名");

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


        //处理客户端消息
        public void run(){
    
    
            try {
    
    
                int falg = 0;     //判断该客户端是否第一次访问
                String fromClientData;

                //循环接收该客户端发送的数据
                while((fromClientData = server_in.readLine()) != null){
    
    
                    //该客户端请求关闭服务器的连接
                    if("exit".equals(fromClientData)){
    
    
                        Server.this.offline(this.client_Name);
                        break;
                    }

                    //判断该客户端是否第一次访问
                    if(falg++ == 0){
    
    
                        this.client_Name = fromClientData;
                        clients.put(this.client_Name,this.client_socket);  
                        sendtoAllClient("欢迎:"+this.client_Name+"进入聊天室");
                        Server.this.showUserList();
                        continue;
                    }

                    //处理私聊    格式  @接收客户端的名字:对其说的话
                    if(fromClientData.startsWith("@")){
    
    
                        String receiveName = fromClientData.substring(1,fromClientData.indexOf(":"));
                        String message = fromClientData.substring(fromClientData.indexOf(":")+1,fromClientData.length());

                        sendtoUser(this.client_Name,receiveName,message);

                    }else {
    
    
                        //处理群发群发
                        sendtoAllClient(this.client_Name+"说:"+fromClientData);
                    }

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

    //显示所有用户列表
    private synchronized  void showUserList(){
    
    
        System.out.println("\n*****用户列表****");
        System.out.println("在线人数:"+clients.size());
        for (Map.Entry<String,Socket> user:clients.entrySet()){
    
    
            System.out.println("---"+user.getKey());
        }
    }

    //广播消息message给所有客户端
    private synchronized  void sendtoAllClient(String message){
    
    
        try {
    
    
            //获取所有客户端套接字socket的输出流
            for (Map.Entry<String,Socket> user:clients.entrySet()) {
    
    
               PrintWriter server_out = new PrintWriter(user.getValue().getOutputStream(),true);
                server_out.println(message);
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }

    //转发消息给某个特定的客户端  
    private synchronized void sendtoUser(String senduser,String receiveuser,String message){
    
    
        try {
    
    
            PrintWriter out = new PrintWriter( clients.get(receiveuser).getOutputStream(),true);
            out.println(senduser+"对你说:"+message);

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


    //某个客户端退出服务器
    private synchronized void offline(String username){
    
    
            clients.remove(username);
            if(username !=  null)
            sendtoAllClient(username+"已下线!");
            Server.this.showUserList();
    }

    public static void main(String[] args) throws Exception {
    
    
        new Server();

    }
}

Cliente

public class Client {
    
    
    private String ip_adress = "127.0.0.1";
    private final int port = 5210;

    private PrintWriter client_out;   //发送消息给服务器的输出流
    private BufferedReader client_in;  //接收服务器消息的输入流
    private Socket client_socket;   //客户端套接字

    public  Client() throws IOException {
    
    
        //1-初始化
        client_socket = new Socket(ip_adress,port); //根据ip,端口连接服务器
        client_in = new BufferedReader(new InputStreamReader(client_socket.getInputStream()));
        client_out = new PrintWriter(client_socket.getOutputStream(),true);
        
        //2-开启新线程处理监听服务器端发来的消息
        new ClientThread().start();

        //3-客户端循环发送群聊,私聊消息
        while(true){
    
    
            //获取客户端的输入
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String input = br.readLine();
            client_out.println(input);  //发送消息给服务器

            //4-客户端退出服务器
            if(input.equals("exit")){
    
    
                client_out.close();
                client_in.close();
                client_socket.close();
                System.exit(0);
            }
        }
    }

   //-----------------------------------------------------------------
    /**
     *          监听服务器端发来的消息
     */
    private class ClientThread extends Thread{
    
    
        public void run(){
    
    
            try {
    
    
            		//接收服务器消息
                    String fromServer_data;
                    while((fromServer_data=client_in.readLine()) != null){
    
    
                         System.out.println(fromServer_data);
                    }
            } catch (IOException e) {
    
    
            }
        }
    }

    
	 //启动客户端
    public static void main(String[] args) throws IOException {
    
    
            new Client();  
    }
}

Recompensa

Si encuentra útil el artículo, puede animar al autor

Inserte la descripción de la imagen aquí


Supongo que te gusta

Origin blog.csdn.net/weixin_41347419/article/details/88630037
Recomendado
Clasificación