Member 13082708 Ответов: 0

[JAVA] серверная / клиентская программа с несколькими клиентами. Клиенты блокируют друг друга на стороне сервера.


Привет,

Я делаю программу чата TCP-сервер / клиент. У меня два клиента. Проблема, с которой я сталкиваюсь, заключается в том, что я могу отправить одно сообщение от одного из клиентов, но затем последовательные сообщения от одного и того же клиента отправляются на сервер, но сервер не передает их, пока я не отправлю сообщение от другого клиента.

Подобный этому:

Клиент1: Привет! (работает)
Клиент1: здравствуйте (ничего)
Клиент2: Здравствуйте! (работает, и появляется второе сообщение Client1)

Это похоже на то, что сервер не сбрасывает свой PrintWriter до тех пор, пока client2 не отправит сообщение? Я явно очищаю PrintWriter как на стороне сервера, так и на стороне клиента.


Вот мой серверный код:

public  void startServer(){
        this.stop = false;
        ServerSocket serverSocket = null;
        
        try {
            serverSocket = new ServerSocket(PORT);
            System.out.println("Server started at " + InetAddress.getLocalHost() + ":" + PORT);
        } catch (IOException ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        while(!stop){
            try {
                Socket socket = serverSocket.accept();                        
                System.out.println("Connection made with " + socket.getInetAddress());                
                EchoConnection conn = new EchoConnection(socket);
                Thread thread = new Thread(conn);
                thread.start();
            } catch (SocketTimeoutException e){
                
            } catch (IOException ex) {
                stop = true;
            }
        }
        
        try {
            serverSocket.close();
        } catch (IOException ex) {
            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
        }
    }



private class EchoConnection implements Runnable {

        private Socket socket;
        private Gson gson;
        PrintWriter printWriter;
        BufferedReader bufferedReader;
        
        public EchoConnection(Socket socket){
            this.socket = socket;
            this.gson = new Gson();            
        }
        
        @Override
        public void run() {            
            try {                    
                printWriter = new PrintWriter(socket.getOutputStream(), true);
                bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
               
                
                String encodedMessage;
                
                do {
                    encodedMessage = bufferedReader.readLine();
                    System.out.println("Received Message! Processing...");
                    
                    if(encodedMessage.contains("userInfo:")){
                        String[] parts = encodedMessage.substring(encodedMessage.indexOf(":") + 1, encodedMessage.length()).split(",");                        
                        String username = parts[0];
                        int udpPort = Integer.parseInt(parts[1]);                        
                        createClient(username, udpPort, socket);
                    }else if(encodedMessage.contains("DISCONNECT:DONE")){
                        System.out.println("Closing connection with " + socket.getInetAddress());
                        removeClientFromList(socket);
                    } else {
                        String messageType = getMessageType(encodedMessage);
                    
                        if(messageType.equals("private")){
                            String newMessage = formatEncodedMessage(encodedMessage);
                            PrivateMessage privateMessage = gson.fromJson(newMessage, PrivateMessage.class);
                            String userTo = privateMessage.getTo();
                            String userFrom = privateMessage.getFrom();
                            String messageToSend = privateMessage.getMessage();                            
                            sendPrivateMessage(userTo, userFrom + ": " + messageToSend);
                        } else if(messageType.equals("broadcast")){
                            String newMessage = formatEncodedMessage(encodedMessage);
                            BroadcastMessage broadcastMessage = gson.fromJson(newMessage, BroadcastMessage.class);
                            sendBroadcastMessage(broadcastMessage.getMessage());
                        } else if(messageType.equals("disconnect")){
                            String newMessage = formatEncodedMessage(encodedMessage);
                            DisconnectMessage disconnectMessage = gson.fromJson(newMessage, DisconnectMessage.class);
                            // TODO: Implement proper disconnect message stating which Client disconnected
                            sendDisconnectMessage(disconnectMessage.getMessage());
                        }             
                    }          
                } while(encodedMessage != null && !encodedMessage.equals("((STOP))"));             
                
            } catch (IOException ex) {
                Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
                try {
                    if(printWriter != null){
                        printWriter.close();
                    }
                    
                    if(bufferedReader != null){
                        bufferedReader.close();
                    }
                    
                    if(socket != null){
                        socket.close();
                    }
                } catch (IOException ex) {
                    Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }



Вот клиентский код:

private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {                                           
        if(btnConnect.getText().equals("Connect to Server")){
            String username = JOptionPane.showInputDialog("Enter your username:");       
            this.username = username;
            
            lblConnectionStatus.setText("Status: Connecting to server...");  
            
            try {
                socket = new Socket(HOST_NAME, HOST_PORT);
            } catch (IOException ex) {
                Logger.getLogger(ClientUI.class.getName()).log(Level.SEVERE, null, ex);
            }

            new Thread(new Runnable(){
                @Override
                public void run() {
                    try {
                        datagramSocket = new DatagramSocket();
                        int udpPort = datagramSocket.getLocalPort();
                        printWriter = new PrintWriter(socket.getOutputStream(), true);
                        bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));            
                        printWriter.println("userInfo:" + username + "," + udpPort);
                        printWriter.flush();
                        receive();

                        String response;

                        do {
                            response = bufferedReader.readLine();
                            txtAreaChat.append(response + "\n");
                        } while(!stop);
                    } catch (IOException ex) {
                        Logger.getLogger(ClientUI.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }            
            }).start();


            lblConnectionStatus.setText("Status: Connected!");
            btnConnect.setText("Disconnect");
        } else if(btnConnect.getText().equals("Disconnect")){
            printWriter.println("DISCONNECT:DONE");
            printWriter.flush();
            stop = true;
            
            try {
                if(printWriter != null){
                    printWriter.close();
                }

                if(bufferedReader != null){
                    bufferedReader.close();
                }

                if(socket != null){
                    socket.close();
                }
                
                lblConnectionStatus.setText("Status: Disconnected");
                btnConnect.setText("Connect to Server");
                listConnected.setListData(new String[0]);
            } catch (IOException ex) {
                Logger.getLogger(ClientUI.class.getName()).log(Level.SEVERE, null, ex);
            }            
        }        
    }  


private void txtMessageKeyPressed(java.awt.event.KeyEvent evt) {                                      
        // If the pressed key is the 'Enter' key
        if(evt.getKeyCode() == KeyEvent.VK_ENTER){
            // Create MessageSender object
            // Trim the whitespace from the text in the message box
            String text = txtMessage.getText().trim();        
        
            // Check if there is an '@' tag at the beggining of the message to indicate a private message
            if(text.startsWith("@")){
                // Get the username
                int beginIndex = text.indexOf("@") + 1;
                int endIndex = text.indexOf(" ");
                String toUser = text.substring(beginIndex, endIndex);
                boolean foundUser = false;
                
                // Check if user is currently online
                for(String onlineUser : currentlyConnected){
                    if(onlineUser.equals(toUser)){
                        foundUser = true;
                        break;
                    }
                }
                
                // If the user is currently online, create a private message object with the message and username
                if(foundUser){
                    beginIndex = text.indexOf(" ") + 1;
                    endIndex = text.length();
                    String message = text.substring(beginIndex, endIndex);

                    PrivateMessage privateMessage = new PrivateMessage(message, username, toUser);
                    String json = privateMessage.toJSON();
                    printWriter.println(json);
                    printWriter.flush();
                // Else notify the user that the user they are trting to send a private message to could not be found (not online/doesn't exist)
                } else {
                    JOptionPane.showMessageDialog(this, "Could not find user " + toUser + "!");
                }  
            // Else, create a broadcast message with the text in the message box
            } else {                
                BroadcastMessage broadcastMessage = new BroadcastMessage(text);
                String json = broadcastMessage.toJSON();
                printWriter.println(json);
                printWriter.flush();
            }
        }      
    }


Что я уже пробовал:

Я пробовал промывать PrintWriter как на стороне сервера, так и на стороне клиента. Я также запускаю каждое клиентское соединение в своем собственном потоке, как показано выше.

0 Ответов