原创

Java MultipleChat 带有语音消息,语音消息由客户端发送,但另一个客户端没有收到它

温馨提示:
本文最后更新于 2024年04月12日,已超过 48 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

We are implementing a Java multiple chat with sockets where with a server and multiple clients, a client needs to send a voice message and it has to be heard by another client. We have the class and the voice message is recorded but it never gets sent.

This is the Server class:

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

public class Server {

    private static Set<PrintWriter> writers = new HashSet<>();
    public static boolean calling = false;
    public static Server_voice sv = new Server_voice(); 

    public static void main(String[] args) {

        sv.init_audio();        
        int PORT = 6789;
        Chatters clientes = new Chatters();

        try {
            ServerSocket serverSocket = new ServerSocket(PORT);
            System.out.println("Servidor iniciado. Esperando clientes...");

            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("Nuevo cliente conectado: " + clientSocket);
                // crea el objeto Runable
                ClientHandler clientHandler = new ClientHandler(clientSocket, clientes);
                // inicia el hilo con el objeto Runnable
                new Thread(clientHandler).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    


}

This is the Client class:

import java.io.*;
import java.net.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Random;
import java.util.Set;
import javax.sound.sampled.*;
import java.io.IOException;

public class Client {
    private static final String SERVER_IP = "127.0.0.1";
    private static final int PORT = 6789;
    private static int AUDIO_PORT_RECEIVER;
    private static int AUDIO_PORT_SENDER;
    private static AudioRecorderPlayer recorderPlayer = new AudioRecorderPlayer();

    public static void main(String[] args) {
        try {
            Socket socket = new Socket(SERVER_IP, PORT);
            System.out.println("Connected to the server.");

            // Generate available ports for audio sender and receiver
            AUDIO_PORT_RECEIVER = findAvailablePort();
            AUDIO_PORT_SENDER = findAvailablePort();

            BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in));
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            OutputStream outputStream = socket.getOutputStream();

            Thread readerThread = new Thread(new Receiver(in, socket));
            readerThread.start();

            Thread senderThread = new Thread(new Sender(userInput, out, outputStream));
            senderThread.start();

            readerThread.join(); // Wait for the receiver thread to finish
            senderThread.join(); // Wait for the sender thread to finish

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

    private static int findAvailablePort() throws IOException {
        try (ServerSocket socket = new ServerSocket(0)) {
            return socket.getLocalPort();
        }
    }

    static class Receiver implements Runnable {
        private BufferedReader in;
        private Socket socket;

        public Receiver(BufferedReader in, Socket socket) {
            this.in = in;
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                String receivedMessage;
                while ((receivedMessage = in.readLine()) != null) {
                    if (receivedMessage.equals("audio")) {
                        // Receive audio
                        receiveAudio();
                    } else if(receivedMessage.equals("CALL")){
                        System.out.println("Llamada empezada!");
                        // Listen for the ip
                        String ip = in.readLine();
                        // Start the call
                        Set<String> ips = Set.of(ip);
                        Thread callSenderThread = new Thread(new CallSender(ips));
                        callSenderThread.start();
                        Thread callReceiverThread = new Thread(new CallReceiver());
                        callReceiverThread.start();
                    } else {
                        // Print other messages
                        System.out.println(receivedMessage);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        private void receiveAudio() throws IOException {
            InputStream inputStream = socket.getInputStream();
            int randomNumber = 1 + new Random().nextInt(100000);
            String fileName = "./Client/audios/received_audio" + randomNumber + ".wav";
            System.out.println("Audio file: " + fileName);

            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
                                new FileOutputStream(fileName));

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) > 0) {
                bufferedOutputStream.write(buffer, 0, bytesRead);
                // Check if the file transfer is complete
                if (inputStream.available() == 0) {
                    break;
                }
            }
            bufferedOutputStream.close();
            System.out.println("Has recibido un audio, lo encontraras en la carpeta audios bajo el nombre: received_audio" + randomNumber + ".wav");
        }
    }

    static class Sender implements Runnable {
        private BufferedReader userInput;
        private PrintWriter out;
        private OutputStream outputStream;

        public Sender(BufferedReader userInput, PrintWriter out, OutputStream outputStream) {
            this.userInput = userInput;
            this.out = out;
            this.outputStream = outputStream;
        }

        @Override
        public void run() {
            try {
                String message;
                while ((message = userInput.readLine()) != null) {
                    if (message.startsWith("/record")) {
                        // Record audio and send
                        recordAndSendAudio(message);
                    } else {
                        out.println(message);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        private void recordAndSendAudio(String message) throws IOException {
            int duration = Integer.parseInt(message.split(" ")[1]);
            recorderPlayer.recordAudio(duration);
            out.println(message);

            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("recorded_audio.wav"));
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            bufferedInputStream.close();

            Path audioFilePath = Paths.get("recorded_audio.wav");
            Files.deleteIfExists(audioFilePath);
        }
    }

    static class CallSender implements Runnable {
        private Set<String> ips;

        public CallSender(Set<String> ips) {
            this.ips = ips;
        }

        @Override
        public void run() {
            try {
                // Initialize audio capture
                AudioFormat format = new AudioFormat(44100, 16, 1, true, false);
                DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
                TargetDataLine line = (TargetDataLine) AudioSystem.getLine(info);
                line.open(format);
                line.start();
                DatagramSocket socket = new DatagramSocket(AUDIO_PORT_SENDER);
                byte[] buffer = new byte[1024];
                while (true) {
                    // Capture audio
                    int bytesRead = line.read(buffer, 0, buffer.length);
    
                    // Send audio to all IPs
                    for (String ip : ips) {
                        InetAddress address = InetAddress.getByName(ip);
                        DatagramPacket packet = new DatagramPacket(buffer, bytesRead, address, AUDIO_PORT_RECEIVER);
                        socket.send(packet);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    static class CallReceiver implements Runnable {
        @Override
        public void run() {
            try {
                // Initialize audio playback
                AudioFormat format = new AudioFormat(44100, 16, 1, true, false);
                DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
                SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info);
                line.open(format);
                line.start();
    
                // Initialize network socket
                DatagramSocket socket = new DatagramSocket(AUDIO_PORT_RECEIVER);
    
                byte[] buffer = new byte[1024];
                while (true) {
                    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                    socket.receive(packet);
                    // Play received audio
                    line.write(packet.getData(), 0, packet.getLength());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}

And the ClientHandler class:

import java.io.*;
import java.net.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;


import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;

import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.List;

class ClientHandler implements Runnable {
    private Socket clientSocket;
    private BufferedReader in;
    private PrintWriter out;
    private String clientName;
    Chatters clientes;

    // Constructor que recibe el socket del cliente y la lista de clientes del chat
    public ClientHandler(Socket socket, Chatters clientes) {
        this.clientSocket = socket;
        this.clientes = clientes;
        try {
            // Se inicializan los flujos de entrada y salida
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream(), true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            // Pedir al cliente que ingrese su nombre
            while (true) {
                out.println("Ingresa tu nombre");
                clientName = in.readLine();
                if (clientName == null) {
                    return;
                }
                synchronized (clientName) {
                    // Verificar si el nombre está disponible y agregar al usuario al chat
                    if (!clientName.isBlank() && !clientes.existeUsr(clientName)) {
                        clientes.broadcastMessage(clientName + " se ha unido al chat.");
                        out.println("NOMBRE ACEPTADO: " + clientName);
                        clientes.addUsr(clientName, out, clientSocket);
                        
                        break;
                    }
                }
            }

           
            String message;
            // Esperar y manejar mensajes de los clientes
            while ((message = in.readLine()) != null) {
                if (message.startsWith("/createGroup")) {
                    handleCreateGroup(message);
                } else if (message.startsWith("/join")) {
                    handleJoinGroup(message);
                } else if (message.startsWith("/group")) {
                    handleGroupMessage(message);
                } else if (message.startsWith("/leaveGroup")) {
                    handleLeaveGroup(message);
                } else if (message.contains(":")) {
                    handlePrivateMessage(message);


                } else if(message.startsWith("/recordAudio")){
                    handleRecordAudio(message, "grupo");
                    
                  
                } else if(message.startsWith("/calling")){
                    new Thread(() -> {
                        try {
                          playCall();
                        } catch (Exception e) {
                          e.printStackTrace();
                        }
                      })
                        .start();

                } else {
                    clientes.broadcastMessage(clientName + ": " + message);
                }
            }
        } catch (IOException e) {
            // Manejar errores de E/S
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // Cerrar el socket y eliminar al usuario del chat al salir
                clientSocket.close();
                System.out.println(clientName + " ha abandonado el chat.");
                clientes.broadcastMessage(clientName + " ha abandonado el chat.");
                clientes.removeUsr(clientName);
            } catch (IOException e) {
                // Manejar errores al cerrar el socket
            }
        }
    }

    private void handleJoinGroup(String message) {
        String[] parts = message.split(" ");
        if (parts.length >= 2) {
            String groupName = parts[1];
            clientes.addUserToGroup(groupName, new Person(clientName, out, clientSocket));
            out.println("Te has unido al grupo '" + groupName + "'.");
        }
    }

    private void handleGroupMessage(String message) {
        String[] parts = message.split(" ", 3);
        if (parts.length >= 3) {
            String groupName = parts[1];
            String groupMessage = parts[2];
            clientes.sendMessageToGroup(groupName, clientName + ": " + groupMessage);
            out.println("Mensaje enviado al grupo '" + groupName + "'.");
        }
    }
    

    private void handleCreateGroup(String message) {
        String[] parts = message.split(" ");
        if (parts.length >= 2) {
            String groupName = parts[1];
            clientes.createGroup(groupName);
            out.println("Grupo '" + groupName + "' creado correctamente.");
        }
    }
    


    private void handleLeaveGroup(String message) {
        String[] parts = message.split(" ");
        if (parts.length >= 2) {
            String groupName = parts[1];
            clientes.removeUserFromGroup(groupName, clientName);
        }
    }

    private void handlePrivateMessage(String message) {
        String[] parts = message.split(":", 2);
        String receiver = parts[0].trim();
        String privateMessage = parts[1].trim();
        clientes.sendMessageToUser(clientName, receiver, privateMessage);
    }

    // Nuevo método para manejar la grabación de audio
    private void handleRecordAudio(String message, String groupName) {
        try {
            // Lógica para grabar el audio desde el socket del cliente y guardar en un archivo
            System.out.println("Grabando audio...");
            InputStream inputStream = this.clientSocket.getInputStream();
            int randomNumber = 1 + new Random().nextInt(100000);
            String fileName = "./db/received_audio" + randomNumber + ".wav";
            System.out.println("Archivo de audio: " + fileName);

            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(fileName));

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) > 0) {
                bufferedOutputStream.write(buffer, 0, bytesRead);
            }
            bufferedOutputStream.close();

            // Obtener el tipo de envío (grupo o usuario) desde el mensaje
            String sendOption = message.split(" ")[1]; // Cambiado a índice 1
            System.out.println("sendOption: " + sendOption);
            
            if (sendOption.equals("group")) {
                handleGroupAudio(fileName, groupName);
            } else if (sendOption.equals("user")) {
                handleUserAudio(message, fileName);
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("Error al grabar audio.");
        }
    }


    // Método para manejar el env<ío de audio a un grupo
    private void handleGroupAudio(String fileName, String groupName) {
        Set<Person> groupMembers = clientes.getGroup(groupName);
        try {
            for (Person member : groupMembers) {
                Socket memberSocket = member.getSocket();
                OutputStream outputStream = memberSocket.getOutputStream();
                FileInputStream fileInputStream = new FileInputStream(fileName);
                BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);

                byte[] buffer = new byte[8192];
                int bytesRead;
                while ((bytesRead = bufferedInputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, bytesRead);
                }

                bufferedInputStream.close();
                outputStream.close();
                fileInputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("Error sending audio to group members.");
        }
    }

    // Método para manejar el envío de audio a un usuario
    private void handleUserAudio(String message, String fileName) {
        String receiver = message.split(" ")[3];
        try {
            clientes.sendAudioToUser(receiver, clientName, fileName);
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("Error sending audio to user.");
        }
    }
        
    
    private void playCall() throws Exception {
        DatagramSocket serverSocket = new DatagramSocket(6789);
        System.out.println("\nServer started. Waiting for clients...\n");
    
        // Configurar la línea de audio para reproducir el audio recibido
        AudioFormat audioFormat = new AudioFormat(44100.0f, 16, 2, true, false);
        DataLine.Info dataLineInfo = new DataLine.Info(
          SourceDataLine.class,
          audioFormat
        );
        SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(
          dataLineInfo
        );
        sourceDataLine.open(audioFormat);
        sourceDataLine.start();
    
        byte[] receiveData = new byte[1024];
    
        while (true) {
          DatagramPacket receivePacket = new DatagramPacket(
            receiveData,
            receiveData.length
          );
          serverSocket.receive(receivePacket);
    
          // Reproducir audio
          sourceDataLine.write(
            receivePacket.getData(),
            0,
            receivePacket.getLength()
          );
        }
      }

}

We have tried multiple changes between classes but more than fixing the issue it makes it worse, not even letting the client enter their users. The idea as described before is that the voice message gets to the other end (Client) and it gets heard, but is not happening.

正文到此结束
热门推荐
本文目录