Click here to Skip to main content
15,892,005 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi,

I'm making a TCP Server/Client chat program. I have two clients. The problem I'm having is that I can send one message from one of the clients, but then consecutive messages from the same client get sent to the server, but the server doesn't pass them on until I send a message from the other client.

Like this:

Client1: Hi! (works)
Client1: Hello (nothing)
Client2: Hello! (works, and Client1's second message appears)

It's sort of like the server isn't flushing it's PrintWriter until client2 sends a message? I'm explicitly flushing the PrintWriter both server- and client-side.


Here's my server code:

Java
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);
        }
    }



Java
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);
                }
            }
        }



Here's the client code:

Java
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);
            }            
        }        
    }  


Java
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();
            }
        }      
    }


What I have tried:

I have tried flushing the PrintWriter both server- and client-side. I am also running each client connection in it's own Thread as shown above.
Posted

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900