Return to Snippet

Revision: 14158
at May 20, 2009 22:25 by mcox05


Initial Code
In a nutshell, I just recently starting attempting to use Sockets and decided I wanted to give a go at a chat program. I have some experience with threads and based on the weird deadlock issues I have come to the conclusion that I must have some non thread-safe calls somewhere. Any help would be appreciated.

*Client-Side Files*
{code}
public class Client extends Thread
{
    private Socket conn;
    private ObjectOutputStream out;
    private ObjectInputStream in;

    public Client()
    {
        conn = null;
        out = null;
        in = null;
    }

    public Client(String ip)
    {
        obsList = new ArrayList<IClientObs>();

        try
        {
            conn = new Socket(ip, 5000);
            if (conn.isConnected())
            {
                out = new ObjectOutputStream(conn.getOutputStream());
                in = new ObjectInputStream(conn.getInputStream());
            }
            notify("Server: Welcome! Connected to '" + conn.getRemoteSocketAddress() + "'.\n");
        }
        catch(IOException e)
        {
            notify("Console: Error while attempting to connect to the server.\n");
            System.err.println("ConnClient:: ConnClient() -> " + e.getMessage() + "\n");
        }
    }

    public Client(Socket pConn)
    {
        obsList = new ArrayList<IClientObs>();

        try
        {
            conn = pConn;
            if (conn.isConnected())
            {
                out = new ObjectOutputStream(conn.getOutputStream());
                in = new ObjectInputStream(conn.getInputStream());
            }
            notify("Server: Welcome! Connected to '" + conn.getRemoteSocketAddress() + "'.\n");
        }
        catch(IOException e)
        {
            notify("Console: Error while attempting to connect to the server.\n");
            System.err.println("ConnClient:: ConnClient() -> " + e.getMessage() + "\n");
        }
    }

    public void run()
    {
        while (conn.isConnected())
        {
            nextMsg();
        }
    }

    public String nextMsg()
    {
        String msg = "";
        try
        {
            msg = (String)in.readObject();
            notify(msg);
        }
        catch(IOException e)
        {
            System.err.println("ConnClient:: nextMsg() -> " + e.getMessage() + "\n");
        }
        catch(ClassNotFoundException e)
        {
            System.err.println("ConnClient:: nextMsg() -> " + e.getMessage() + "\n");
        }
        finally
        {
            //notify("Console: Error while attempting to read messages from server.\n");
        }
        return(msg);
    }

    public boolean sendMsg(String msg)
    {
        boolean sentMsg = false;
        try
        {
            if (out != null)
            {
                out.writeObject(msg);
                out.flush();
                sentMsg = true;
            }
        }
        catch(IOException e)
        {
            notify("Console: Error while attempting to send message to server.\n");
            System.err.println("ConnClient:: sendMsg() -> " + e.getMessage() + "\n");
        }
        return(sentMsg);
    }

    public void closeConn()
    {
        try
        {
            if (conn != null && in != null && out != null)
            {
                notify("Server: you have been disconnected from '" + conn.getRemoteSocketAddress() + "'.\n");
                sendMsg("~~QUIT~~");
                conn.close();
                in.close();
                out.close();
            }
        }
        catch(IOException e)
        {
            notify("Console: Error while closing connection.");
        }
    }

    public String getIP()
    {
        return(conn.getRemoteSocketAddress().toString());
    }

    public boolean isConnected()
    {
        return(conn.isConnected());
    }

    private ArrayList<IClientObs> obsList;

    public void addObserver(IClientObs obs)
    {
        if (obs != null)
        {
            obsList.add(obs);
        }
    }

    public void delObserver(IClientObs obs)
    {
        if (obs != null)
        {
            obsList.remove(obs);
        }
    }

    private void notify(String msg)
    {
        for(IClientObs obs : obsList)
            obs.update(msg);
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

public interface IClientObs
{
    public void update(String msg);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

public class ClientGui implements ActionListener, KeyListener, IClientObs
{
    private JLabel statusLbl;
    private JTextField chatTB, ipTB;
    private JTextArea txtArea;
    private JButton submitBtn, connectBtn, disconnBtn;
    private JList membList;
    private Container cont;
    private JFrame frame;

    private Client client;
    
    public ClientGui()
    {   
        init("Client Chat");
        
        frame.setBounds(100,100,600,500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
    
    private void init(String title)
    {
        frame = new JFrame(title);
        cont = frame.getContentPane();
        submitBtn = new JButton("Send");
        connectBtn = new JButton("Connect");
        disconnBtn = new JButton("Disconnect");
        txtArea = new JTextArea();
        chatTB = new JTextField(30);
        ipTB = new JTextField(16);
        statusLbl = new JLabel("Status:: Not Connected");
        membList = new JList(new String[]{"admin"});
        JLabel ipLbl = new JLabel("IP Address:");
        JPanel paneE = new JPanel();
        
        txtArea.setEditable(false);
        paneE.setLayout(new BorderLayout());
        
        Box boxS = new Box(BoxLayout.X_AXIS);
        boxS.add(chatTB);
        boxS.add(Box.createHorizontalStrut(2));
        boxS.add(submitBtn);
        
        Box boxC = new Box(BoxLayout.Y_AXIS);
        boxC.add(new JScrollPane(txtArea));
        boxC.add(Box.createVerticalStrut(5));
        
        Box boxE = new Box(BoxLayout.Y_AXIS);
        boxE.add(new JLabel("IP Address:"));
        boxE.add(ipTB);
        
        Box boxI = new Box(BoxLayout.X_AXIS);
        boxI.add(connectBtn);
        boxI.add(Box.createHorizontalStrut(2));
        boxI.add(disconnBtn);
        
        boxE.add(boxI);
        boxE.add(Box.createVerticalStrut(5));
        
        paneE.add(boxE, BorderLayout.NORTH);
        paneE.add(membList, BorderLayout.CENTER);
        
        cont.add(statusLbl, BorderLayout.NORTH);
        cont.add(boxC, BorderLayout.CENTER);
        cont.add(boxS, BorderLayout.SOUTH);
        cont.add(paneE, BorderLayout.EAST);
        
        ipLbl.setHorizontalAlignment(SwingConstants.LEFT);
        boxE.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
        statusLbl.setPreferredSize(new Dimension((int)statusLbl.getSize().getWidth(), 30));
        membList.setBorder(BorderFactory.createLineBorder(Color.black));
        txtArea.setEditable(false);
        
        connectBtn.addActionListener(this);
        disconnBtn.addActionListener(this);
        submitBtn.addActionListener(this);
        chatTB.addKeyListener(this);
    }
    
    private void connect()
    {
        String ip = ipTB.getText();
        client = new Client(ip);
        client.addObserver(this);
        client.start();

        connectBtn.setEnabled(false);
        disconnBtn.setEnabled(true);
        submitBtn.setEnabled(true);
    }
    
    private void disconnect()
    {
        client.closeConn();
        client = null;

        connectBtn.setEnabled(true);
        disconnBtn.setEnabled(false);
        submitBtn.setEnabled(false);
    }
    
    private void sendData()
    {
        if (client != null && client.isConnected())
        {
            String msg = chatTB.getText();
            client.sendMsg(msg);
        }
    }
    
    public void actionPerformed(ActionEvent e)
    {
        Object src = e.getSource();
        if (src == submitBtn)
        {
            sendData();
        }
        else if (src == connectBtn)
        {
            connect();
        }
        else if (src == disconnBtn)
        {
            disconnect();
        }
    }
    
    public void keyPressed(KeyEvent e)
    {
        
    }
    
    public void keyReleased(KeyEvent e)
    {
        
    }
    
    public void keyTyped(KeyEvent e)
    {
        int key = e.getKeyChar();
        if (key == KeyEvent.VK_ENTER)
            sendData();
    }

    public void update(String msg)
    {
        txtArea.append(msg);
    }
}
{code}

*Server-Side Files*
{code}
public class ConnClient extends Thread
{
    private Socket conn;
    private ObjectOutputStream out;
    private ObjectInputStream in;

    public ConnClient()
    {
        conn = null;
        out = null;
        in = null;
    }

    public ConnClient(Socket pConn)
    {
        try
        {
            conn = pConn;
            if (conn.isConnected())
            {
                out = new ObjectOutputStream(conn.getOutputStream());
                in = new ObjectInputStream(conn.getInputStream());
            }

        }
        catch(IOException e)
        {
            System.err.println("ConnClient:: ConnClient() -> " + e.getMessage() + "\n");
        }
    }

    public String nextMsg()
    {
        String msg = "";
        try
        {
            msg = (String)in.readObject();
        }
        catch(IOException e)
        {
            System.err.println("ConnClient:: nextMsg() -> " + e.getMessage() + "\n");
        }
        catch(ClassNotFoundException e)
        {
            System.err.println("ConnClient:: nextMsg() -> " + e.getMessage() + "\n");
        }
        catch(NullPointerException e)
        {
           System.err.println("ConnClient:: nextMsg() -> " + e.getMessage() + "\n");
        }
        return(msg);
    }

    public boolean sendMsg(String msg)
    {
        boolean sentMsg = false;
        try
        {
            if (out != null)
            {
                out.writeObject(msg);
                out.flush();
                sentMsg = true;
            }
        }
        catch(IOException e)
        {
            System.err.println("ConnClient:: sendMsg() -> " + e.getMessage() + "\n");
        }
        return(sentMsg);
    }

    public void closeConn() throws IOException
    {
        if (conn != null && in != null && out != null)
        {
            conn.close();
            in.close();
            out.close();
        }
    }

    public String getIP()
    {
        return(conn.getRemoteSocketAddress().toString());
    }

    public boolean isConnected()
    {
        return(conn.isConnected());
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

public interface IServerObs
{
    public void update(String msg);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

public class ServerGui implements ActionListener, IServerObs
{
    private JFrame frame;
    private Container cont;
    private JButton strBtn, stpBtn;
    private JTextArea console;

    private Server server;
    
    public ServerGui()
    {
        frame = new JFrame("Chat Server");
        cont = frame.getContentPane();
        strBtn = new JButton("Start Server");
        stpBtn = new JButton("Stop Server");
        console = new JTextArea();
        
        strBtn.addActionListener(this);
        stpBtn.addActionListener(this);

        Box b = Box.createHorizontalBox();
        b.add(strBtn);
        b.add(Box.createHorizontalStrut(3));
        b.add(stpBtn);
        
        cont.add(new JScrollPane(console), BorderLayout.CENTER);
        cont.add(b, BorderLayout.SOUTH);
               
        Toolkit kit = frame.getToolkit();
        Dimension d = kit.getScreenSize();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(d.width/4, d.height/4,
                        ((int)(d.width/1.75)), ((int)(d.height/1.75)));
        frame.setVisible(true);
    }

    public void actionPerformed(ActionEvent e)
    {
        Object src = e.getSource();
        if (src == strBtn)
        {
            if (server == null)
            {
                strBtn.setEnabled(false);
                stpBtn.setEnabled(true);

                server = new Server();
                server.addObserver(this);
                server.start();
            }
            else
            {
                console.append("Console: Server is alread initiated.\n");
            }
        }
        else if (src == stpBtn)
        {
            strBtn.setEnabled(true);
            stpBtn.setEnabled(false);

            server.shutdown();
            server = null;
            console.append("Console: Server has been stopped.\n");
        }
    }

    public void update(String msg)
    {
        console.append("Console: " + msg + "\n");
    }
}
{code}

lol, sorry for so much code but I figured it would be necessary for context and figuring out where the problem is.

Initial URL


Initial Description


Initial Title
Client/Server Chat Program

Initial Tags


Initial Language
Java