Socket Listener - I almost have it

116 Views Asked by At

I've been fighting with this and my own poor coding skills apparently.

I'm trying to create a small desktop app that will act essentially as a "Socket Listener" where I can display any information sent to the localhost IP and any port I designate. I have the program working without a UI, but I wanted to make it an actual desktop app (part of my learning journey).

I've searched around and borrowed some ideas from others and almost have it working.

When I launch the app, enter a port number and then try to connect to it using PUTTY I don't see anything displaying in my JTextArea. What should appear is a "Waiting for client" message and then when connected a "Client connected" message, then, of course, any text I type into PUTTY.

If I try connecting using PUTTY, type some text, then exit putty, all of that text and the messages above will appear in the JTextArea (JTextArea is at the bottom of the code).

What on earth am I doing wrong here?

import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import java.awt.Font;
import javax.swing.SwingConstants;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.charset.StandardCharsets;
import java.awt.event.ActionEvent;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.JTextArea;

public class Server extends JFrame {

    private JPanel contentPane;
    private JTextField portInput;
    static int sessionNum = 1;
    static String IPNum = "127.0.0.1";
    public JButton btnListen;
    private JTextField textField;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Server frame = new Server();
                    frame.setVisible(true);


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

    /**
     * Create the frame.
     */
    public Server() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 570, 503);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JLabel lblAddress = new JLabel("IP Address:");
        lblAddress.setHorizontalAlignment(SwingConstants.RIGHT);
        lblAddress.setFont(new Font("Tahoma", Font.PLAIN, 16));
        lblAddress.setBounds(10, 29, 81, 27);
        contentPane.add(lblAddress);

        JLabel lblDisplayAddress = new JLabel("127.0.0.1");
        lblDisplayAddress.setFont(new Font("Tahoma", Font.PLAIN, 16));
        lblDisplayAddress.setBounds(101, 29, 81, 27);
        contentPane.add(lblDisplayAddress);

        JLabel lblPort = new JLabel("Port: ");
        lblPort.setHorizontalAlignment(SwingConstants.RIGHT);
        lblPort.setFont(new Font("Tahoma", Font.PLAIN, 16));
        lblPort.setBounds(210, 33, 90, 19);
        contentPane.add(lblPort);

        portInput = new JTextField();
        portInput.setFont(new Font("Tahoma", Font.PLAIN, 16));
        portInput.setBounds(297, 31, 111, 22);
        contentPane.add(portInput);
        portInput.setColumns(10);

        btnListen = new JButton("LISTEN");
        btnListen.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {

                int portNum =  Integer.parseInt(portInput.getText());

                try{
                    ServerSocket ss=new ServerSocket(portNum, sessionNum, InetAddress.getByName(IPNum));
                    System.out.println("Waiting for client.........");
                    Socket s=ss.accept();//establishes connection
                    System.out.println("Client connected.........");
                    var rawIn = s.getInputStream();
                    var in = new BufferedReader(new InputStreamReader(rawIn, StandardCharsets.UTF_8)); {


                        while (true){
                            String cmd = in.readLine();
                            if (cmd == null) break; //client is hung up
                            if (cmd.isEmpty()) continue; //empty line was sent
                            System.out.println("Client sent: " + cmd);
                        }

                        System.out.println("Closing connection");

                        s.close();
                    }

                }catch(IOException i){System.out.println(i);}

            }
        });
        btnListen.setFont(new Font("Tahoma", Font.PLAIN, 16));
        btnListen.setBounds(450, 31, 89, 23);
        contentPane.add(btnListen);

        JTextArea output = new JTextArea();
        output.setBounds(10, 77, 536, 382);
        contentPane.add(output);
        PrintStream out = new PrintStream(new OutputStream() {
            @Override
            public void write(int b) throws IOException {
                output.append(""+(char)(b & 0xFF));
            }
        });
        System.setOut(out);


    }
}

UPDATED

Thank you so much for the input. I've incorporated your changes and it is so unbelievably close.

One question. When I run the current code (below), Why doesn't the JTextArea show the "Waiting for client..." message right away? It shows up once PUTTY connects, but not before.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import java.awt.Font;
import javax.swing.SwingConstants;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.charset.StandardCharsets;
import java.awt.event.ActionEvent;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.JTextArea;

public class Server extends JFrame {

    private JPanel contentPane;
    private JTextField portInput;
    static int sessionNum = 1;
    static String IPNum = "127.0.0.1";
    public JButton btnListen;
    private JTextField textField;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Server frame = new Server();
                    frame.setVisible(true);


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

    /**
     * Create the frame.
     */
    public Server() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 570, 503);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JLabel lblAddress = new JLabel("IP Address:");
        lblAddress.setHorizontalAlignment(SwingConstants.RIGHT);
        lblAddress.setFont(new Font("Tahoma", Font.PLAIN, 16));
        lblAddress.setBounds(10, 29, 81, 27);
        contentPane.add(lblAddress);

        JLabel lblDisplayAddress = new JLabel("127.0.0.1");
        lblDisplayAddress.setFont(new Font("Tahoma", Font.PLAIN, 16));
        lblDisplayAddress.setBounds(101, 29, 81, 27);
        contentPane.add(lblDisplayAddress);

        JLabel lblPort = new JLabel("Port: ");
        lblPort.setHorizontalAlignment(SwingConstants.RIGHT);
        lblPort.setFont(new Font("Tahoma", Font.PLAIN, 16));
        lblPort.setBounds(210, 33, 90, 19);
        contentPane.add(lblPort);

        portInput = new JTextField();
        portInput.setFont(new Font("Tahoma", Font.PLAIN, 16));
        portInput.setBounds(297, 31, 111, 22);
        contentPane.add(portInput);
        portInput.setColumns(10);

        btnListen = new JButton("LISTEN");
        btnListen.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {

                int portNum =  Integer.parseInt(portInput.getText());

                try {
                    ServerSocket ss = new ServerSocket(portNum, sessionNum, InetAddress.getByName(IPNum));
                    System.out.println("Waiting for client.........");
                    Socket s = ss.accept();// establishes connection
                    Thread t = new Thread(new Runnable() {
                        public void run() {
                            try {
                                System.out.println("Client connected.........");
                                var rawIn = s.getInputStream();
                                var in = new BufferedReader(new InputStreamReader(rawIn, StandardCharsets.UTF_8));
                                {
                                    while (true) { // Don't do this on the EDT.
                                        String cmd = in.readLine();
                                        if (cmd == null)
                                            break; // client is hung up
                                        if (cmd.isEmpty())
                                            continue; // empty line was sent
                                        System.out.println("Client sent: " + cmd);
                                    }

                                    System.out.println("Closing connection");

                                    s.close();
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    });
                    t.start();
                } catch (IOException i) {
                    System.out.println(i);
                }
            }
        });
        btnListen.setFont(new Font("Tahoma", Font.PLAIN, 16));
        btnListen.setBounds(450, 31, 89, 23);
        contentPane.add(btnListen);

        JTextArea output = new JTextArea();
        output.setBounds(10, 77, 536, 382);
        contentPane.add(output);
        PrintStream out = new PrintStream(new OutputStream() {
            @Override
            public void write(int b) throws IOException {
                output.append(""+(char)(b & 0xFF));
            }
        });
        System.setOut(out);


    }
}

1

There are 1 best solutions below

7
Elliott Frisch On

You have a ServerSocket blocking to read the client connection on the Event Dispatch Thread. Spawn a new thread when you accept a connection. Something like,

btnListen.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {

        int portNum = Integer.parseInt(portInput.getText());

        try {
            ServerSocket ss = new ServerSocket(portNum, sessionNum, InetAddress.getByName(IPNum));
            System.out.println("Waiting for client.........");
            final Socket s = ss.accept();// establishes connection
            Thread t = new Thread(new Runnable() {
                public void run() {
                    try {
                        System.out.println("Client connected.........");
                        var rawIn = s.getInputStream();
                        var in = new BufferedReader(new InputStreamReader(rawIn, StandardCharsets.UTF_8));
                        {
                            while (true) { // Don't do this on the EDT.
                                String cmd = in.readLine();
                                if (cmd == null)
                                    break; // client is hung up
                                if (cmd.isEmpty())
                                    continue; // empty line was sent
                                System.out.println("Client sent: " + cmd);
                            }

                            System.out.println("Closing connection");

                            s.close();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            t.start();
        } catch (IOException i) {
            System.out.println(i);
        }
    }
});